feat(ui): add forecast champion selector foundation#359
Conversation
There was a problem hiding this comment.
Sorry @w7-mgfcode, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Closes #356 · Slice A of 3 (A → B → C) of the Forecast Champion Selector.
PRP:
PRPs/forecast-champion-selector-slice-a-selection-capability.md.First interactive Champion Selector surface — configuration + availability
triage. It deliberately stops before running the comparison (that is Slice B)
and before any training/prediction/promotion (Slice C).
Backend
GET /model-selection/models→ModelCatalogResponse— a backend-ownedcapability catalog (one entry per forecasting
ModelType, 11 total), declaredbefore
GET /{selection_id}so Starlette matches the literal path (not aselection_idcapture).capabilities.py(build_model_catalog(), no DB/IO); eachentry carries
model_type,label,family(derived fromforecasting.feature_metadata.model_family_for),feature_aware,requires_extra,default_params,supports_auto_predict,description,plus a
default_candidate_model_typeslist.feature_aware== the set whose forecasters setrequires_features=True(random_forest/regression/lightgbm/xgboost/prophet_like) — i.e. exactly the
set
ForecastingService.predict()rejects.requires_extra== {lightgbm, xgboost};supports_auto_predict==not feature_aware.default_paramspinned from the liveModelConfigdefaults.ModelSelectionService.get_model_catalog()thin delegate; response schemasCandidateModelInfo+ModelCatalogResponseadded toschemas.py.Frontend
/visualize/championpage shell (pages/visualize/champion.tsx) — lazyroute + Visualize nav entry. Store → Product → Time period → Horizon → Models
→ Backtest settings, plus a live availability panel.
components/champion-selector/:searchable-entity-select(Popover +Input + filtered list — no new dependency),
availability-panel(ready/limited/unusable + metrics + recommended split; not-enough-data empty
state),
backtest-settings-form(simple/advanced split,SplitConfigbounds,WAPE-default ranking metric with the locked tie-break + bias copy),
candidate-model-picker(catalog-fed, family-grouped, opt-in-extra badges,cap 10), plus
copy.ts/split-config.ts/run-request.tshelpers.hooks/use-model-selection.ts:useModelCatalog+usePairAvailability(availability gated on a valid pair).
types/api.ts: full Model-Selection workflow contract added (Slice Aconsumes catalog/availability/
SplitConfigonly; the run/ranking/chart/forecasttypes are declared-for-later so Slices B/C inherit, not redefine).
Scope boundaries
Slice B wires the
POSTmutation. The page assembles a typedModelSelectionRunRequest(withauto_train_winner:false/auto_predict:falsepinned, both no-ops in the async path) but never sends it.
no winner explanation/business summary, no train/predict/override/promotion.
Exactly one new backend route; no calls to any
/{selection_id}*endpoint.Validation
ruff check .+ruff format --check✅pytest -m "not integration"✅ 1753 passed, 12 skipped (incl. 8 newtest_capabilities+ 2 new/modelsroute/ordering tests)pnpm tsc --noEmit✅ ·pnpm lint✅ (exit 0; only a pre-existing TanStackTable warning remains) ·
pnpm test --run✅ 282 passed (28 new Champion tests)pyright app/features/model_selection✅ 0 errorsKnown pre-existing (NOT introduced here)
mypy app//pyright app/reportlightgbm/xgboostoptional-depimport-resolution errors in
forecasting/+registry/(CI installs theextras). None are in
model_selection; documented in the PRP's Level-4 notes.