Compare a challenger model's holdout metric vs the incumbent's and recommend
promote (challenger wins by ≥ margin) or hold. Pure / synchronous — reads
the frozen HoldoutMetrics JSON off both models. This is a RECOMMENDATION; no
promotion is performed here (that is a separate signed-off Action).
the current model
the freshly-retrained model
the resolved policy (margin + comparison metric)
Decide whether a binding's model is stale per policy. Pure with respect to the injected seams: reads counts/drift via deps and the clock, mutates nothing.
the MJ: ML Model Scoring Bindings row
the MJ: ML Models row the binding scores with
the staleness/retraining policy (partial → merged with defaults)
the injected dependency bundle
Re-score a Mode='Scheduled' binding and stamp its monitoring fields
(LastScoredAt = now, LastRowCount = scoredCount). Bindings that are not
Scheduled are skipped (returns null).
the binding to re-score
the model it scores with
the injected dependency bundle
the re-score result, or null when the binding is not Scheduled
Run the full maintenance pass over a set of bindings — the entry the scheduler
(or an Action) calls. For each binding: load its model, detect staleness,
optionally re-score (Scheduled bindings), and optionally retrain+compare when
stale. Each binding is isolated: a failure is captured on its entry and the
pass continues.
the bindings to maintain (resolve via the loader for "all scheduled")
the staleness/retraining policy (partial → merged with defaults)
the injected dependency bundle
pass toggles (re-score scheduled / retrain stale)
Retrain when stale: if staleness.stale, retrain the binding's model against
the SAME pipeline → a new immutable version, then compare the challenger's
holdout metric vs the incumbent's and return a promotion RECOMMENDATION
(promote / hold). Never auto-promotes.
the binding whose model may be retrained
the current (stale) model
the staleness verdict driving the decision
the policy (for the promotion margin + comparison metric)
the injected dependency bundle (carries the training engine + deps)
OptionaltrainInputOverrides: Partial<Omit<TrainModelInput, "pipelineId">>optional extra train inputs (labelEventDates / maxRows / etc.)
Maintenance orchestrator. Stateless across calls; construct once and reuse. The dependency bundle (MaintenanceDeps) and RetrainingPolicy are supplied per call.