Skip to content

make the "Measure this model" gate a routable sidebar instead of a modal - #4805

Merged
atomantic merged 3 commits into
mainfrom
cos/task-mt3pmw8i/agent-e6bde2f3
Aug 22, 2026
Merged

make the "Measure this model" gate a routable sidebar instead of a modal#4805
atomantic merged 3 commits into
mainfrom
cos/task-mt3pmw8i/agent-e6bde2f3

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

  • The "Measure this model" consent gate is now a routable Drawer instead of a Modal. Which model is open lives in the URL — ?measureBackend=&measureModel=&measureTuning= on /models/performance — so the gate is shareable, bookmarkable and survives a reload, the same rule the AI-provider editor follows at /ai/edit/:providerId.
  • Search params, not a path segment, because a model id is not one: it carries / and : (hf.co/org/repo:Q4_K_M), and the drawer is an overlay on an already-routed tab.
  • The consent contract is unchanged — the gate still names the backend, model and generation count before any provider call, and closing it still aborts a run in flight.
  • A deep link naming a record the report no longer lists opens with a notice instead of bouncing — the same id is legitimately absent for the moment between a first run landing and the refreshed report arriving.
  • The tuning form is derived from the record the URL names, so a re-measure reproduces that configuration; a background report refresh can't overwrite a half-typed knob.
  • The Drawer's icon-only close button now announces "Stop the assessment" while a run is in flight, rather than the primitive's default "Close settings".

Follow-up filed as #4803: the sibling per-model Sweep tunings gate is still a modal, so two consent gates on the same row now behave differently.

Test plan

  • client suite: LocalModelAssessments.test.jsx 48/48 — the 42 existing tests now render inside a MemoryRouter, plus 6 new ones covering the routable behavior (URL written on open, deep link opens with no click, tuning seeded from the record a link names, notice for an unlisted id, URL cleared on cancel and on a completed run).
  • client/src/components/settings/ + Models.test.jsx + a11yConventions.test.js: 311/311.
  • Full client suite green; the two failures seen under parallel load (Catalog.test.jsx, a11yConventions.test.js) pass in isolation and are unrelated load flakes.
  • biome lint --error-on-warnings src: clean.

Which model the assessment gate has open now lives in the URL
(?measureBackend / measureModel / measureTuning on /models/performance)
rather than in local state, so it is shareable, bookmarkable and survives a
reload — the same rule the AI-provider editor follows at /ai/edit/:providerId.
Search params rather than a path segment because a model id is not one: it
carries `/` and `:` (`hf.co/org/repo:Q4_K_M`), and the drawer is an overlay on
an already-routed tab.

The consent contract is unchanged (it still names the backend, model and
generation count before any provider call, and closing still aborts a run in
flight). A deep link that names a record the report no longer lists opens the
drawer with a notice instead of bouncing, and the tuning form is seeded once
from that record so a re-measure reproduces its configuration.
Review follow-ups, all behavior-preserving:

- `openTarget` / `closeTarget` hand-rolled the merge-and-prune URLSearchParams
  loop `useUrlParams` owns (client/src/hooks/README.md says not to re-roll it),
  and re-adopted the closure-stale functional `setSearchParams` updater the hook
  exists to close over.
- The tuning form seeded a state copy through a ref + effect to avoid a
  background report refresh clobbering a half-typed knob. Deriving the draft
  from the record — with an "edited yet?" override — does the same in four lines.
- The target carried a `resolved` flag alongside a `reportLoaded` prop that the
  drawer recombined; the parent now computes `unknownTarget` once.
- Row lookup re-spelled the composite identity `entryKey` already encodes, and
  copied every model in the report into one array to run a single find.
- Dropped the leftover Modal heading: the Drawer header already renders the
  title and the model id.
The Drawer's icon-only header button aborts an in-flight assessment, but kept
the primitive's default "Close settings" accessible name — a screen-reader user
had no way to know that pressing it kills a multi-minute run.
@atomantic
atomantic merged commit 3bf34d0 into main Aug 22, 2026
7 checks passed
@atomantic
atomantic deleted the cos/task-mt3pmw8i/agent-e6bde2f3 branch August 22, 2026 02:05
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