pub(crate) fn train_model(samples: &[TreeSample]) -> Result<TrainResult, String>Expand description
Fit a tree and compute the holdout metrics, on the training worker.
The tree is fit on the first 90% of the window and evaluated on the
last 10%, so the reported MAE and the publish gate describe
out-of-sample error. The EMA baseline is exact. Each sample’s
prediction is the captured gauge feats.ema (the post-decay gauge at
the capture, as emitted by the BPF side), so
mae_ema = mean(|feats.ema - label|) on the same holdout slice and
the tree comparison is honest.