v0.5.1 (2026-07-13)
v0.5.1 is a durability-and-polish follow-up to v0.5.0. Its one substantial change makes a published run’s media survive the loss of the volumes it was read from, the lesson of a cluster recreate that wiped both the backend’s ephemeral store and the artifact service’s PVC. The rest is a batch of console fixes and the deployment that rolls v0.5.0 into production.
Features
Section titled “Features”Run media is exported once, under content-stable keys
Section titled “Run media is exported once, under content-stable keys”A published run’s media, meaning its proof-of-implementation images and videos
and an asset-generation run’s produced files, now lives under a
snapshot-independent
media/runs/<id>/ prefix keyed by
the run id, outside any single snapshot’s prefix. It is written once and
referenced by every later snapshot, instead of being re-read, re-uploaded, and
for video re-transcoded on each publish.
On each publish the snapshot builder lists what is already present under
media/runs/ and, for anything already there, references it in the per-run
document without reading the source bytes or re-uploading. A publish therefore
stays cheap as asset-generation runs accumulate, and because the public snapshot
bucket has no GC, a run’s media persists even after the volumes the bytes were
read from are gone. A per-run document still names its media by the
served-filename basename the site keys on, so the contract is preserved. If the
existing-media listing fails, the publish degrades to re-exporting everything
rather than aborting the refresh. See
snapshot.
Recovering run media from a prior snapshot
Section titled “Recovering run media from a prior snapshot”A new scripts/recover-run-media-from-snapshot.{sh,mjs} restores run media
after the recreate case where both the backend store and the artifact service
PVC were wiped: it copies each published run’s proof/asset media from a prior
public snapshot prefix (the surviving copy in R2) back into the backend store
and triggers a single refresh. It’s the counterpart to backfill-run-media.sh,
which sources from the artifact service and so can’t help when that volume is
gone. scripts/lib/env.sh gains a per-environment TCAB_SNAPSHOT_URL (the
public snapshot read base), and the backups doc adds the
missing run-media row and a Recreating a cluster runbook.
The seeded model picker shows the full catalog again
Section titled “The seeded model picker shows the full catalog again”The New Run form seeds each combination row’s model with a concrete slug, so the
ModelCombobox’s value is a committed selection rather than a query. The
dropdown substring-matched its options against that value, collapsing the whole
catalog down to the one selected model. It now narrows the list only while the
user is actively typing; a committed/seeded value (or focus) shows every model
again. The Coverage config picker, which reuses the component, is covered too.
The active list reflects a run’s real phase
Section titled “The active list reflects a run’s real phase”A launched run was tracked optimistically as running, and the active-list
reconcile only ever added new runs or pruned finished ones, never refreshing the
phase of an already-tracked run. So a run held back at its harness’s parallelism
cap (pending) or spinning up its driver and container (starting) sat as
running the whole time. A just-enqueued run is now tracked as queued (its
true backend state), and reconcileActiveRuns emits phase updates for tracked
runs whose reported state has advanced. Phase updates don’t require a complete
worker picture and never resurrect a run locally marked failed.
Pagination stops reverting to page 1
Section titled “Pagination stops reverting to page 1”useResetPageOnChange listed setPage in its effect dependencies, but
react-router v7 rebuilds the search-params setter on every location.search
change. Clicking to page 2 changed setPage’s identity, re-firing the reset
effect and snapping the list back to page 1, so the URL updated for a split
second then reverted. The hook now reacts only to its resetKey, holding the
latest setPage in a ref and tracking the previous key, so genuine sort/scope
changes still reset while page navigation is left alone.
The static /models page no longer crashes
Section titled “The static /models page no longer crashes”useModelConfig() called useBackend(), which asserts a <BackendProvider> is
mounted. The static gallery mounts none, so /models threw and rendered
nothing. A new useOptionalBackend() (mirroring useOptionalWorkers) reads the
client, so a missing provider now reads as an unconfigured backend and the
model-config affordance hides on the static site instead of crashing the page.
The pricing chart stops warning on a short history
Section titled “The pricing chart stops warning on a short history”The price-over-time line left its z channel implicit, so Plot inferred it from
stroke: "series" and warned about high implicit-z cardinality whenever the
series count exceeded half the point count, which a short history (a single
observation: one Input and one Output point) always trips. Naming z: "series"
explicitly, the per-series grouping we already want, silences it.
Deployment
Section titled “Deployment”Staging and prod roll to v0.5.0, in lockstep
Section titled “Staging and prod roll to v0.5.0, in lockstep”Both azure overlays now pin the v0.5.0 release build a74d1414: staging moves
its service images from 9bb4858e and its TCAB_CONTAINER_TAG from 8b5953a3;
prod moves its service images from v0.4.1 (b3c2b322) and its
TCAB_CONTAINER_TAG from v0.4.0 (ba19bd69). Unlike v0.4.1, the v0.5.0 work
touched the asset-generation and foray crates that build-containers watches,
so the run images were republished at the same sha, putting service and run
images back in lockstep on one git sha. Both clusters applied and rolled out
green, all workloads Running against managed Postgres.
Reference implementations published to prod
Section titled “Reference implementations published to prod”The non-experimental cases’ reference implementations are now published to prod
as well as staging; test-cases/reference-builds.lock.json gains the prod
entries the backend ingests during catalog reconciliation. See reference
implementations.