Slice C of 3 — Forecast Decision, Business Summary + Operationalization
Closes the champion-selection workflow after comparison (Slices A #356 + B #360 merged). Adds the decision half: accept the recommended winner or override to another candidate (warned + audited), train it, generate + read its forecast, surface a business-readable interpretation, and — through an explicit, approval-gated, audited path — promote the trained champion to a registry alias.
PRP: PRPs/forecast-champion-selector-slice-c-forecast-decision-operationalization.md
Backend (additive to model_selection slice)
POST /model-selection/{id}/train-selected — train a user-chosen candidate (override + audit); returns override_warning.
POST /model-selection/{id}/predict — KEEP existing behavior; ADD optional ForecastDecisionParams body; response gains peak/low + a decision block (safety stock, expected demand, bias-risk).
POST /model-selection/{id}/promote — approval-gated, audited registry orchestration (create_run → SUCCESS w/ verified artifact → create_alias); persists champion_run_id/promoted_alias/promotion_decision.
- Pure
app/features/model_selection/decision.py (z-table, King safety-stock heuristic, peak/low, bias-risk text).
- One Alembic migration: 7 additive columns on
model_selection_run (incl. feature_frame_version for V2 promotion).
Frontend (extends /visualize/champion)
- Hooks:
useTrainWinner/useTrainSelected/usePredictWinner/usePromoteChampion.
components/champion-selector/decision/* family (override panel, train/forecast actions w/ capability-limited state, summary card, chart, daily table, business-interpretation panel, safety-stock panel, promote dialog).
- Additive types in the "Model Selection" section.
Docs + dogfood
docs/user-guide/champion-selector-guide.md + cross-link.
- End-to-end manual dogfood (select → run → decide → train → forecast → promote) over localhost.
Success criteria
Slice C of 3 — Forecast Decision, Business Summary + Operationalization
Closes the champion-selection workflow after comparison (Slices A #356 + B #360 merged). Adds the decision half: accept the recommended winner or override to another candidate (warned + audited), train it, generate + read its forecast, surface a business-readable interpretation, and — through an explicit, approval-gated, audited path — promote the trained champion to a registry alias.
PRP:
PRPs/forecast-champion-selector-slice-c-forecast-decision-operationalization.mdBackend (additive to
model_selectionslice)POST /model-selection/{id}/train-selected— train a user-chosen candidate (override + audit); returnsoverride_warning.POST /model-selection/{id}/predict— KEEP existing behavior; ADD optionalForecastDecisionParamsbody; response gains peak/low + adecisionblock (safety stock, expected demand, bias-risk).POST /model-selection/{id}/promote— approval-gated, audited registry orchestration (create_run → SUCCESS w/ verified artifact → create_alias); persistschampion_run_id/promoted_alias/promotion_decision.app/features/model_selection/decision.py(z-table, King safety-stock heuristic, peak/low, bias-risk text).model_selection_run(incl.feature_frame_versionfor V2 promotion).Frontend (extends
/visualize/champion)useTrainWinner/useTrainSelected/usePredictWinner/usePromoteChampion.components/champion-selector/decision/*family (override panel, train/forecast actions w/ capability-limited state, summary card, chart, daily table, business-interpretation panel, safety-stock panel, promote dialog).Docs + dogfood
docs/user-guide/champion-selector-guide.md+ cross-link.Success criteria
train-selectedoverride persistsis_override+override_reason, returnsoverride_warning; non-candidate → 400.predictreturns peak/low + labeleddecision; safety stock never feeds ranking; feature-aware → clean 400 + UI blocked state.promoterequiresapproved_by; non-recommended-no-ack → 422; before-train → 422; bad alias_name → 422; success creates SUCCESS registry run + alias + audit.feature_frame_version(V2 → 2); downgrade clean.