pub(crate) fn split_holdout(
samples: &[TreeSample],
) -> Result<(&[TreeSample], &[TreeSample]), String>Expand description
Split the window into the fit slice (first 90%) and the held-out evaluation slice (last 10%). The daemon only trains once the window holds MLFQ_TREE_MIN_SAMPLES samples, so the holdout is never empty in production; a window too small for a meaningful 90/10 split (< 20 samples) is an error, which the caller treats as a skipped training round (log + keep the previous model) instead of silently training and evaluating on the same slice.