π§ͺ Metadata Diff β demo branch (tool is #6753) - #6615
Conversation
|
Quick links (staging server):
Login: chart-diff: βNo charts for review.data-diff: β 2 changed Β· 3 identical β full report~ garden/wb/2026-06-26/world_bank_pip
~ incomes.thr (changed metadata)
~ garden/wid/2026-06-18/world_inequality_database
~ inequality.gini (changed metadata)
~ inequality.p50_p10_ratio (changed metadata)
~ inequality.p90_p10_ratio (changed metadata)
~ inequality.p90_p50_ratio (changed metadata)
~ inequality.palma_ratio (changed metadata)
~ inequality.s80_s20_ratio (changed metadata)
~ inequality.s90_s10_ratio (changed metadata)
~ inequality.s90_s50_ratio (changed metadata)
~ inequality.share_bottom_50 (changed metadata)
~ inequality.share_middle_40 (changed metadata)
~ inequality.share_top_0_1 (changed metadata)
~ inequality.share_top_1 (changed metadata)
~ inequality.share_top_10 (changed metadata)
~ inequality.share_top_90_99 (changed metadata)
~ relative_poverty.headcount_ratio (changed metadata)
~ incomes.avg (changed metadata)
~ incomes.mean (changed metadata)
~ incomes.median (changed metadata)
~ incomes.share (changed metadata)
~ incomes.thr (changed metadata)= 3 compared dataset(s) turned out identical; details in the full report Automatically updated datasets matching excess_mortality|covid|fluid|flunet|country_profile|garden/ihme_gbd/2019/gbd_risk are not included. Run locally with Edited: 2026-08-26 09:16:24 UTC |
Clean, frozen copy of the Metadata Diff wizard tool on a fresh branch off master (so its staging carries no leftover test metadata). Includes the gender-gap-in-average-wages-ilo WYSK as a ready chart example to try. Affected-charts reveal is a popover (clean window), not a show/hide button; scope defaults to 'only this view'.
β¦ tool) Wealth-branch of description_key_welfare_type reworded from 'This measure is related to household net wealthβ¦' to 'Wealth is defined as household net wealthβ¦' β an MDim/WID example to exercise the review tool.
nowcast_regions_description reworded to match description_key_regional_global_
estimates in the incomes MDim ('extrapolated to the year⦠growth estimates and
forecasts from [national accounts](#dod:national-accounts)') β test example.
β¦st radius The PR brief guessed a single best-guess variable Key and reported the reach of only the group's first indicator. For a shared `definitions.*`/anchor edit (one Jinja template rendering into many indicators) that was both a wrong edit target and an undercounted reach. - Collect every indicator id + catalogPath carrying an identical shared change into the ChangeGroup, and add `distinct_indicator_short_names` to fingerprint a shared definition (identical text on >1 indicator). - Brief now points at the shared definition (grep the text, edit `definitions.`/ `shared.meta.yml`, not `tables.<t>.variables.<short>`) and labels the diff reach as a floor. - Union usage across all of a group's indicators (`_group_usage`) so "apply to all" and the review scope label count every affected chart/MDim, not just one indicator's.
β¦them "10 charts" is not something an author can check. Applying a shared change to all means those specific charts change, so both the PR brief and the in-app decision now list them by slug. - `_surface_lines` enumerates affected charts (linked) and other MDims for a change group, in the Apply section of both the MDim and chart briefs. Under a scoped decision the same list is shown as what keeps the old text. - Charts that render no data page (multi-indicator) are flagged: a WYSK edit is not visible to their readers. - Choosing "Apply to all" in the View diff now surfaces the full list of surfaces at the moment of the decision, not just a count.
The edited nowcast_regions_description in garden/wb/2026-06-26/shared.py is only imported by world_bank_pip_legacy.py. The live PIP MDims are built on garden/wb/2026-06-26/world_bank_pip, which does not import shared.py, so the edit changed nothing (owidbot's data-diff reported the dataset as identical). Dropping it; the tool demo keeps the ILO and WID test changes.
Merge the two opening sentences of description_key_thr into one, so the bullet leads with what the data shows instead of restating it: "This data lets you compare incomes across deciles, or tenths of the population. The data shows the income threshold dividing each decile." -> "The data shows the income threshold dividing each decile, or tenth of the population." Only the non-median branch is touched: decile 5 renders definitions.description_key_median and is unaffected.
β¦ edit
The brief told the executor not to edit the variable directly, then handed them a
pastable description_key block containing the fully *rendered* bullets. Pasting it
would hardcode rendered text under the variable and destroy the Jinja branches for
every other dimension β the payload contradicted the instruction.
- For a shared-definition change, show the changed bullet(s) as a diff (the one line
to find and replace inside the definition) instead of the full field YAML. A plain
per-variable field still gets the pastable block.
- Reword the reach caveat: the diff only sees indicators used by this MDim, so say so
('at least N ... within this MDim alone') instead of the misleading 'all N+'.
- Mark the attribution placeholders as needing to be filled in.
Rendering the brief for a single-indicator definition (PIP incomes.thr) showed the
same hazard the shared-definition case had: thr's description_key is authored as
seven {definitions.*} refs including a branched one, so pasting the rendered
two-bullet YAML over it would drop six definitions and the decile-5 median branch.
The 'more than one indicator' test doesn't catch that.
The changed line is always the safe minimal edit, so show it first in every case.
The full rendered value stays for reference, explicitly marked not-pastable unless
the field is authored literally.
β¦st their config The βοΈ marker compared only the MDim's own configMd5, which is the wrong signal for this tool: a text edit is authored in the garden step and reaches the MDim through indicator metadata, leaving the config byte-identical. The WID wealth MDim we edited showed no marker, while an MDim whose config moved without any text change showed one. - get_mdim_changes now also compares the user-visible metadata of every indicator each MDim references (two chunked variables lookups; ~32 MDims / ~1.2k indicators total), exposing indicator_changed and has_changes alongside config_changed. - The marker uses the union; the help text explains both signals. - If the indicator comparison fails, fall back to the config signal and say so in the UI rather than silently showing fewer markers.
Adding `config` to the MDim list query made MySQL sort rows carrying that large JSON blob (the query has `order by updatedAt desc`), overrunning the server's sort buffer and breaking the whole page. - The ordered list query goes back to its lightweight column list; configs are fetched by a separate unordered query, the pattern usage.py already uses safely. - Cache the MDim list + change flags (st.cache_data, 300s) so the indicator comparison doesn't re-query on every Streamlit rerun.
β¦ chart text Folds lessons from the edit-faust-metadata skill (#6519, #6568) that this brief was missing. Text only β no counting logic or queries changed. - Ship-it gains a 'surfaces this brief did NOT check' item for shared changes: narrative charts (an inheriting child keeps showing the OLD text until its patch is re-saved), explorer views (not queried; legacy CSV explorers are invisible to the DB tables), and data insights / static viz / key-chart slots / article embeds. Points at find-chart-references for the full sweep and blast_radius.py --field for per-field inheritance. An unlisted surface reads as 'nothing else is affected'. - title_public / description_short also feed a chart's title / subtitle by inheritance, and a chart setting its own value is shielded β it keeps that text. Mark the chart list an upper bound for those two fields and name the command that resolves it. (WYSK is unaffected: a chart config can't carry description_key.) - The PR-description blast-radius line says what the counts cover.
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 286fe71d9c
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce7e6454c2
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5fb6d3f684
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 585e7eff8f
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 223f739fc1
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5c4535083
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 035dd08694
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 75dac83b06
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b00e65d4c
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9bcb516545
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd619c3ad3
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31b626f883
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3cc3ddbc04
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a8fe90311
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d43b0188b
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dcbe7692e9
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d66c7bd46c
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: βΉοΈ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with π. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
63169de to
e430262
Compare
# Conflicts: # etl/steps/data/garden/un/2026-02-03/ilostat.meta.yml
Grapher replaced chart_configs.patch + full with a single `config` column, so every query selecting `cc.full ->> '$.title'` now fails with "Unknown column 'cc.full'" and 500s the MDim view diff. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
β¦rked Three changes, all about what a section shows you first. **Per-item views are back, from #6615, with the navigation taken out of the way.** That branch had a View diff page (one MDim, one view at a time, reached by assembling a dimension selection) and a chart flow you typed a slug into. Both answered a question the change-grouped lists cannot β "what happened to *this* view / *this* chart" β and both made you navigate before showing you anything. So: - **MDims β View by view**: every changed view of an MDim, already on the page, each with its own diffs and a link that opens it (admin preview when the MDim is unpublished). A card shows three and folds the rest; `π Open view by view` gives one MDim its own paginated page, addressable as `?mdim-views=<path>`. - **Charts β Chart by chart**: every changed chart, ordered by how much changed, naming the fields and linking to its own review. Plus a searchable picker β "Open one of the 67 changed charts" β which is the thing that was missing: you could reach a chart's review only by typing its slug. - **Explorers β View by view**: the same for explorer views. **Item view is the default in all three**, with `𧬠By change` one click away under a shared `?layout=` key. Grouping by change is still the right shape for judging an edit β one reworded sentence listed once, with the eight hundred pages it reaches underneath β it is just not what someone arriving at the page is usually asking. **The review sign-off is out of the UI for now**: no Reviewed toggles, no "k/n reviewed" counters, no π‘/β per change, and the section badges are back to plain names. Parked, not deleted β `review_state.py` and the table stay, and the summary still identifies every distinct change, because the badges and the greyed-when-empty rule count changes rather than ticks. Two tests the last review round added pinned "every change past the cap keeps its Reviewed toggle". The controls are gone, so they are replaced by one test pinning the half that survives and is what the finding was really about: a card that says it holds N changes renders N changes. It asserts on a single inserted token per change, because the diff renders word by word and a rewritten sentence comes back split across <ins>/<del> tags. The stale-label serde test is deleted outright β it failed on its own precondition ("the labels must differ, or there is nothing to defend against"), which is exactly right now that a label is just a name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
β¦w page #6615's View diff had two controls this page was missing: a β‘ jump to a changed view, and the MDim's own dimension menu. Restored β and restored the way that branch wired them, which is the part worth copying: the jump renders nothing itself, it *writes into* the menu, so there is only ever one answer on screen to "which view am I looking at". β‘ Changes detected β jump to a changed view (51) Indicator Group Period Breaks in data Mean incomeβ¦ nan Per day Don't show Two differences, both following from the page being a list first: - every dimension may be left unset, so the menu **filters** as well as focuses. Verified: `?dim-indicator=mean` alone reports "6 of 51 changed views match the menu above" and lists them. #6615 forced a complete selection, which is how it could land you on "No view exists for this combination". - with nothing set you still see every changed view. The menu narrows; it is not the way in. A complete selection shows that view **whether or not it changed** β "did the view I was worried about move?" is a question only an unchanged view can answer, and it says so plainly rather than rendering an empty diff. The jump writes the dimension widgets' session state from a callback, which is the only order that works: a widget reads its session value when it is created, so setting it afterwards is a change nobody sees until the next rerun. Stale values are dropped before the widget is built β widening a dimension above can strand the one below, and `url_persist` raises on a value that is no longer an option. Every choice is URL-visible, so one view of one MDim is a link somebody else can open: `?mdim-views=<path>&dim-decile=nan&dim-period=day&dim-indicator=mean&β¦` Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
π§ͺ Demo branch β the tool itself is now #6753
Not for merge, and never was. This branch carries metadata edits (WID wealth WYSK, PIP nowcast and decile-threshold bullets) purely so a staging server has something for the tool to find. Without them there is nothing to look at.
The tool is #6753 β reviewable, on current master, without any metadata edit, in three commits. Review it there.
What this branch is
The first version of Metadata Diff, as it stood on 5 August: a wizard page that compares the rendered user-facing texts β chart titles, subtitles, footnotes,
description_short, WYSK /description_keyβ between a staging server and the baseline, catching edits authored in garden steps that no config diff shows.It has been reset to that state (
e430262938) on purpose. Everything built afterwards β discovery instead of search, the Blast radius section, branch attribution, stale-server detection, the owidbot service, the performance work β lives in #6753.The full 54-commit history of that development is kept at the tag
metadata-diff-tool-history(63169de97a), so nothing is lost; it is out of the way because much of it is us changing our minds, including work that later commits delete.Known limitation of this branch
It predates grapher removing
chart_configs.fullin favour ofconfig, so its queries read a column that no longer exists on production or on a rebuilt staging server: expectUnknown column 'cc.full'where it reads chart text. #6753 follows master's migration. If you want a live demo, the honest options are to run it from #6753's branch with a throwaway metadata edit, or to cherry-pick the column change onto this one.π€ Generated with Claude Code