From 29f36bb1d694e6abc3cb82933942d5ebdd860142 Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Tue, 3 Mar 2026 09:26:53 +0100 Subject: [PATCH] docs(ml): clarify edge-case comments from final review - ab_testing: clarify champion_dd == 0 drawdown semantics - online_learning: document compute_fisher independent-loss requirement - curriculum: document disabled-vs-override precedence Co-Authored-By: Claude Opus 4.6 --- crates/ml/src/deployment/ab_testing.rs | 5 +++-- crates/ml/src/trainers/curriculum.rs | 4 ++-- crates/ml/src/trainers/online_learning.rs | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/ml/src/deployment/ab_testing.rs b/crates/ml/src/deployment/ab_testing.rs index 6481673c9..eecce97ba 100644 --- a/crates/ml/src/deployment/ab_testing.rs +++ b/crates/ml/src/deployment/ab_testing.rs @@ -642,8 +642,9 @@ impl PromotionCriteria { }; } - // 3. Drawdown constraint: challenger DD must not exceed ratio * champion DD - // Guard against champion_dd == 0: any positive challenger_dd would fail. + // 3. Drawdown constraint: challenger DD must not exceed ratio * champion DD. + // When champion_dd == 0, dd_limit == 0 so any positive challenger_dd fails + // (correctly strict). Both == 0 passes (both perfect — valid). let dd_limit = champion_dd * self.max_drawdown_ratio; if challenger_dd > dd_limit { return PromotionDecision::NotReady { diff --git a/crates/ml/src/trainers/curriculum.rs b/crates/ml/src/trainers/curriculum.rs index 7ec58b5fc..cd49951d6 100644 --- a/crates/ml/src/trainers/curriculum.rs +++ b/crates/ml/src/trainers/curriculum.rs @@ -76,8 +76,8 @@ pub struct CurriculumScheduler { impl CurriculumScheduler { /// Create a new scheduler. /// - /// If `config.override_phase` is set, the scheduler starts in that phase. - /// If curriculum learning is disabled, the scheduler starts in `AllRegimes`. + /// Precedence: `!enabled` (→ AllRegimes) > `override_phase` > default (Basic). + /// When disabled, `override_phase` is ignored — all actions/regimes are allowed. pub fn new(config: CurriculumConfig) -> Self { let initial_phase = if !config.enabled { CurriculumPhase::AllRegimes diff --git a/crates/ml/src/trainers/online_learning.rs b/crates/ml/src/trainers/online_learning.rs index e87f9c5d9..cb47b1fbc 100644 --- a/crates/ml/src/trainers/online_learning.rs +++ b/crates/ml/src/trainers/online_learning.rs @@ -183,6 +183,10 @@ impl EWCRegularizer { /// accumulate the squared gradient magnitudes (diagonal Fisher approx): /// /// F_i = (1/N) * sum_n (d loss_n / d theta_i)^2 + /// + /// **Important**: each element of `losses` must come from an independent + /// forward pass. Calling `backward()` consumes gradients, so reusing a + /// loss tensor that has already been back-propagated produces zero grads. pub fn compute_fisher( &mut self, var_map: &VarMap,