- New runs are tagged on dispatch with dataset:<id> / algorithm:<short> /
N:<n> / T:<t> / J:<j> (single value per axis).
- /runs accepts ?dataset=&algorithm=&N=&T=&J= and applies Prefect's
tags: {all_: [...]} server-side. Without filter, fetch cap is 10; with
filter, 50 so narrow results aren't truncated. Prefect's own 200-limit
on filter queries is clamped inside recent_runs.
- New /runs/axes.json returns the universe of chip values across the last
200 deployment runs so the chip bar shows history even when the current
slice is narrow.
- runs-filter.js rewritten to cassette-style single-select: clicking the
selected chip releases it. No 'all'/'none' meta chips. Chip state feeds
#runs-slot via hx-vals; a filter-changed custom event triggers an
immediate refetch on change, in addition to the 3s poll.
- Prefect client gets an update_tags(run_id, tags) helper.
- scripts/backfill_tags.py PATCHes tags onto every existing deployment
run (dry-run by default, --apply to commit).
- run_args_hash now covers (embed_args, generator_kwargs). When gen_kwargs
is empty we still hash embed_args alone — so plain generators (s_curve,
plain swiss_roll) keep their stems and no existing plain-gen figs need
renaming. Kwargs-bearing variants (swiss_roll_hole, blobs,
gaussian_quantiles, classification) now disambiguate properly.
- Flow persists generator_kwargs into metrics.json meta AND into the
frames.json sidecar meta, so the label-enrichment path can find it
without another lookup.
- _enrich_with_labels discovers gen_kwargs in priority: payload meta -->
sibling metrics.json --> DATASET_META first-match. It matches the
DATASET_META entry by (path, kwargs) so swiss_roll_hole is no longer
confused for plain swiss_roll.
- _cached_frames overrides meta.stem with the URL-requested stem before
enrichment — after a backfill rename the sidecar's baked-in stem is
stale, and we were then failing to find the sibling metrics.json.
- Submit duplicate-check uses the new hash and keeps the hashless-legacy
check as a safety net.
- backfill_hashes.py rewritten: queries Prefect for each recent run's
full params, finds the matching fig under any of (current, legacy,
hashless) names, renames to the current scheme and patches
generator_kwargs into metrics.json.
Reads each legacy <stem>.metrics.json for its embed_args, computes the
same sha1-8 digest main.py uses, renames the .html and its sidecars in
place. Skips Reference figs (no embed_args) and any fig lacking a
metrics.json (can't recover the hash from a missing sidecar).