Slice A of 3 (A → B → C) — Forecast Champion Selector
First usable frontend/backend surface for the Forecast Champion Selector. Builds on the merged model_selection backend (#353).
Scope (Slice A only)
Backend
GET /model-selection/models → ModelCatalogResponse (backend-owned capability catalog), declared before GET /{selection_id} (route-ordering safety).
- New pure module
app/features/model_selection/capabilities.py (build_model_catalog()), response schemas, thin ModelSelectionService.get_model_catalog().
- No migration, no mutation surface, no agent tool.
Frontend
/visualize/champion page (route + Visualize nav entry, lazy-loaded).
components/champion-selector/ family: searchable store/product selects, availability panel, simple/advanced backtest-settings form, catalog-fed candidate-model picker, disabled "Run comparison" CTA.
hooks/use-model-selection.ts (catalog + availability queries).
- Full Model-Selection TS contract in
types/api.ts (A consumes read-only; B/C inherit).
- Request assembled with
auto_train_winner:false / auto_predict:false (no-ops in the async path).
Explicitly NOT in Slice A
- No
POST /model-selection/run (or any mutation) call; no ranking charts / winner explanation.
- No Slice B (async run/progress/cancel/results) or Slice C (train/predict/business summary/override/promotion).
Acceptance
- Backend Level-1..4 gates green; frontend
tsc/lint/test green.
- PRP:
PRPs/forecast-champion-selector-slice-a-selection-capability.md
Slice B (async run + results) and Slice C (decision layer) follow as separate issues.
Slice A of 3 (A → B → C) — Forecast Champion Selector
First usable frontend/backend surface for the Forecast Champion Selector. Builds on the merged
model_selectionbackend (#353).Scope (Slice A only)
Backend
GET /model-selection/models→ModelCatalogResponse(backend-owned capability catalog), declared beforeGET /{selection_id}(route-ordering safety).app/features/model_selection/capabilities.py(build_model_catalog()), response schemas, thinModelSelectionService.get_model_catalog().Frontend
/visualize/championpage (route + Visualize nav entry, lazy-loaded).components/champion-selector/family: searchable store/product selects, availability panel, simple/advanced backtest-settings form, catalog-fed candidate-model picker, disabled "Run comparison" CTA.hooks/use-model-selection.ts(catalog + availability queries).types/api.ts(A consumes read-only; B/C inherit).auto_train_winner:false/auto_predict:false(no-ops in the async path).Explicitly NOT in Slice A
POST /model-selection/run(or any mutation) call; no ranking charts / winner explanation.Acceptance
tsc/lint/testgreen.PRPs/forecast-champion-selector-slice-a-selection-capability.mdSlice B (async run + results) and Slice C (decision layer) follow as separate issues.