v0.9.3 — tier-chain reordering that sticks, and a keyboard path for it
Highlights
- Dragging models to reorder a tier chain now lands where you dropped it. The chain is
the fallback policy — position 0 is the primary everyauto/tier-routed request hits first
— so a reorder that silently reverted left you believing you had configured one routing
policy while the proxy ran another. Two independent defects caused it. Drag state was keyed
by a list index that was re-read after the reorder had already been applied, so it tracked
the drop target rather than the row you grabbed; for an adjacent swap that became a stable
oscillator, flipping the order back and forth at the browser's drag-event rate with the
pointer held perfectly still, and which order survived depended on where that oscillation
happened to be when you released. Separately, a chain write's response or a routing refresh
arriving mid-drag repainted the whole chain from server state and threw the reorder away —
reachable by dragging within a round-trip of any other chain edit, or simply by leaving the
Routing page and coming back while a refresh was still in flight. - Reordering no longer flickers. A reorder now commits only once the pointer crosses the
target row's midpoint, so jitter on a row boundary stops re-triggering it, and the row hover
highlight no longer chases rows as they move under a stationary pointer. - The drop is properly accepted. It was resolving as a cancelled drag, which made the
browser animate the row snapping back to where it started — reading as "it didn't take" even
when the order had persisted.dragstartalso sets drag data now, which browsers require in
order to begin an HTML5 drag at all. - New: reorder a chain from the keyboard. The
⋮⋮handle is a real button — focus it and
press Alt+↑ / Alt+↓ to move an entry, with focus
following the row and the new position announced to screen readers. Previously Make
primary was the only keyboard route and could only reach position 0, so there was no way to
order one fallback against another without a mouse. CALIBRATION_*andEVENTS_*set in.envnow reach the container. The shipped
docker-compose.ymlis an explicitenvironment:allow-list and neither namespace was on
it, so all thirteen knobs silently kept their defaults — with nothing in the logs to explain
why. Unset behaviour is unchanged.
Upgrade notes
- No migration, no schema change, no new environment variable. The reorder work is
frontend-only and the persisted contract is unchanged (an orderedmodelIdsreplace,
≤ 5 models, position 0 = primary). - If you were setting any
CALIBRATION_*orEVENTS_*variable in.envand quietly getting
defaults, those values take effect on your nextdocker compose up. Review them before
restarting if you had tuned around the defaults.SEMANTIC_*is deliberately unaffected —
those belong todocker-compose.semantic.ymland the-semanticimage. - Hardening that ships alongside: the tier writer is now identity-generation tagged, so a chain
write or tier deletion that completes after a sign-out can no longer write into the next
session's state or surface the previous session's error.
Full package changelogs live in packages/*/CHANGELOG.md.