Split the monolithic ml crate (260K lines, 55s compile) into 5 crates: ml-core, ml-rl, ml-supervised, ml-infra, ml (facade). 15-task plan with full module inventory and import migration guide. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
29 KiB
ML Crate Split Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Split the monolithic ml crate (260K lines, 55s compile) into 5 crates that compile in parallel, reducing incremental rebuilds from 55s to ~10-15s.
Architecture: 4 sub-crates (ml-core, ml-rl, ml-supervised, ml-infra) + thin ml facade that re-exports everything. External consumers see no API changes.
Tech Stack: Rust workspace, Cargo features, pub use re-exports.
Reference: See docs/plans/2026-03-07-ml-crate-split-design.md for full module inventory and dependency analysis.
Phase 1: Preparation (in worktree .worktrees/ml-crate-split, branch feature/ml-crate-split)
Task 1: Verify Clean Baseline
Files: None modified
Step 1: Run full workspace check
Run: cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-crate-split && SQLX_OFFLINE=true cargo check --workspace 2>&1 | tail -5
Expected: Finished with 0 errors
Step 2: Run ml tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Expected: test result: ok with 2506+ tests
Step 3: Record baseline
Note the exact test count and build time for comparison after split.
Task 2: Create Sub-Crate Directory Structure
Files:
- Create:
crates/ml-core/Cargo.toml - Create:
crates/ml-core/src/lib.rs - Create:
crates/ml-rl/Cargo.toml - Create:
crates/ml-rl/src/lib.rs - Create:
crates/ml-supervised/Cargo.toml - Create:
crates/ml-supervised/src/lib.rs - Create:
crates/ml-infra/Cargo.toml - Create:
crates/ml-infra/src/lib.rs - Modify:
Cargo.toml(workspace root — add members + workspace deps)
Step 1: Create crate directories
mkdir -p crates/ml-core/src crates/ml-rl/src crates/ml-supervised/src crates/ml-infra/src
Step 2: Add workspace members
In root Cargo.toml, add to [workspace] members:
"crates/ml-core",
"crates/ml-rl",
"crates/ml-supervised",
"crates/ml-infra",
And add workspace dependency entries:
ml-core = { path = "crates/ml-core" }
ml-rl = { path = "crates/ml-rl" }
ml-supervised = { path = "crates/ml-supervised" }
ml-infra = { path = "crates/ml-infra" }
Step 3: Create minimal Cargo.toml for each sub-crate
Each sub-crate gets a Cargo.toml with:
- Same edition/rust-version as
ml - Dependencies subset (only what its modules need)
- Feature flags relevant to its modules
ml-coreas dependency forml-rl,ml-supervised,ml-infra
See the detailed Cargo.toml specs in Tasks 5-8.
Step 4: Create stub lib.rs for each
Each gets an empty pub mod list initially:
// crates/ml-core/src/lib.rs
// Placeholder — modules moved in subsequent tasks
Step 5: Verify workspace compiles
Run: SQLX_OFFLINE=true cargo check --workspace 2>&1 | tail -5
Expected: Compiles (empty crates are valid)
Step 6: Commit
git add crates/ml-core crates/ml-rl crates/ml-supervised crates/ml-infra Cargo.toml
git commit -m "feat(ml): scaffold sub-crate directory structure for ml split"
Phase 2: Build ml-core (Foundation)
Task 3: Extract Shared Items from dqn/ to Top-Level Modules
These items live in dqn/ but are used by PPO, trainers, ensemble, hyperopt — they belong in ml-core.
Files:
- Move:
crates/ml/src/dqn/mixed_precision.rs→crates/ml/src/mixed_precision.rs - Move:
crates/ml/src/dqn/xavier_init.rs→crates/ml/src/xavier_init.rs - Move:
crates/ml/src/dqn/portfolio_tracker.rs→crates/ml/src/portfolio_tracker.rs - Move:
crates/ml/src/dqn/action_space.rs→crates/ml/src/action_space.rs - Move:
crates/ml/src/dqn/order_router.rs→crates/ml/src/order_router.rs - Modify:
crates/ml/src/dqn/mod.rs— replace module declarations with re-exports - Modify:
crates/ml/src/lib.rs— addpub modfor new top-level modules - Modify: All files importing these via
crate::dqn::*path
Step 1: Move files
cd crates/ml/src
mv dqn/mixed_precision.rs mixed_precision.rs
mv dqn/xavier_init.rs xavier_init.rs
mv dqn/portfolio_tracker.rs portfolio_tracker.rs
mv dqn/action_space.rs action_space.rs
mv dqn/order_router.rs order_router.rs
Step 2: Update dqn/mod.rs
Replace the old pub mod declarations with re-exports so existing crate::dqn::X paths still work:
// In dqn/mod.rs, REPLACE:
// pub mod mixed_precision;
// pub mod xavier_init;
// pub mod portfolio_tracker;
// pub mod action_space;
// pub mod order_router;
// WITH:
pub use crate::mixed_precision;
pub use crate::xavier_init;
pub use crate::portfolio_tracker;
pub use crate::action_space;
pub use crate::order_router;
Step 3: Add modules to ml/lib.rs
Add these lines to lib.rs:
pub mod mixed_precision;
pub mod xavier_init;
pub mod portfolio_tracker;
pub mod action_space;
pub mod order_router;
Step 4: Fix internal imports in moved files
In each moved file, change use crate::dqn:: imports to use crate:: where referencing peer modules (e.g., mixed_precision.rs may import from dqn internals — fix those paths).
Specific fixes needed:
action_space.rs: has nocrate::dqn::imports (only std/serde) — no changes neededxavier_init.rs: usescandle_core/candle_nnonly — no changes neededmixed_precision.rs: usescandle_coreonly — no changes neededportfolio_tracker.rs: check forcrate::dqn::imports and fixorder_router.rs: importscrate::dqn::action_space::*→ change tocrate::action_space::*; importscrate::common::action::*→ keep as-is
Step 5: Verify compilation
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
Expected: Compiles with 0 errors (re-exports preserve all paths)
Step 6: Run tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Expected: Same test count as baseline, 0 failures
Step 7: Run clippy
Run: SQLX_OFFLINE=true cargo clippy -p ml -- -D warnings 2>&1 | tail -10
Expected: 0 errors, 0 warnings
Step 8: Commit
git add -A crates/ml/
git commit -m "refactor(ml): extract shared items from dqn/ to top-level modules
Move mixed_precision, xavier_init, portfolio_tracker, action_space,
order_router from dqn/ to ml/src/ root. These are shared infrastructure
used by PPO, trainers, hyperopt, and ensemble — not DQN-specific.
Re-export from dqn/mod.rs for backward compatibility."
Task 4: Write ml-core Cargo.toml
Files:
- Create:
crates/ml-core/Cargo.toml
Step 1: Write Cargo.toml
Build by examining crates/ml/Cargo.toml and including ONLY dependencies used by ml-core modules. Key deps:
candle-core,candle-nn,candle-optimisers(for mixed_precision, xavier_init, Adam, gpu)common,config,data(workspace crates)tokio,serde,thiserror,anyhow,chrono,tracing(core utilities)arrow,parquet(for features/)dbn,databento(for data_loaders/)rust_decimal(financial types)nalgebra,ndarray,num-traits(for features math)dashmap,lru(for caching in features/)sha2,hmac,hex(for security/)flate2,memmap2(for checkpoint/)- NOT:
argmin(hyperopt only), NOT model-specific deps
Feature flags:
[features]
default = ["cuda"]
cuda = ["candle-core/cuda", "candle-core/cudnn", "candle-nn/cuda", "candle-nn/cudnn"]
s3-storage = ["aws-config", "aws-sdk-s3", "aws-types", "aws-credential-types", "urlencoding"]
high-precision = ["rust_decimal/serde-float"]
mimalloc-allocator = ["mimalloc"]
simd = []
gc = []
financial = []
minimal-inference = []
Step 2: Verify it parses
Run: cargo check -p ml-core 2>&1 | head -5 (will fail on missing modules, that's OK — just verifying Cargo.toml syntax)
Step 3: Commit
git add crates/ml-core/Cargo.toml
git commit -m "feat(ml-core): write Cargo.toml with dependency subset"
Task 5: Move Core Modules to ml-core
This is the largest single task. Move all modules assigned to ml-core.
Files:
- Move: ~30 modules from
crates/ml/src/tocrates/ml-core/src/ - Modify:
crates/ml-core/src/lib.rs— declare all modules - Modify:
crates/ml/src/lib.rs— remove moved modules, addpub use ml_core::*
Step 1: Move type definitions from lib.rs
Extract the type definitions (Trade, MarketRegime, CommonError, CommonTypeError, MLError, HealthStatus, MarketDataSnapshot, FeatureVector, IntegerTensor, UpdateSummary, ModelPrediction, InferenceResult, ModelMetadata, Features, MLModel, HFTPerformanceProfile, ParallelExecutor, LatencyOptimizer, ModelRegistry helpers, and all From impls for MLError) from crates/ml/src/lib.rs into crates/ml-core/src/lib.rs.
Keep the crate-level attributes (#![deny(...)], #![allow(...)]) in both — ml-core gets the canonical set, ml facade gets a minimal subset.
Step 2: Move modules
# Core infrastructure
mv crates/ml/src/error.rs crates/ml-core/src/
mv crates/ml/src/types crates/ml-core/src/
mv crates/ml/src/common crates/ml-core/src/
mv crates/ml/src/config crates/ml-core/src/
mv crates/ml/src/cuda_compat.rs crates/ml-core/src/
mv crates/ml/src/tensor_ops.rs crates/ml-core/src/
mv crates/ml/src/traits.rs crates/ml-core/src/
mv crates/ml/src/model.rs crates/ml-core/src/
mv crates/ml/src/optimizers crates/ml-core/src/
mv crates/ml/src/gradient_accumulation.rs crates/ml-core/src/
mv crates/ml/src/gradient_utils.rs crates/ml-core/src/
mv crates/ml/src/gpu crates/ml-core/src/
mv crates/ml/src/safety crates/ml-core/src/
mv crates/ml/src/security crates/ml-core/src/
mv crates/ml/src/memory_optimization crates/ml-core/src/
mv crates/ml/src/checkpoint crates/ml-core/src/
mv crates/ml/src/training crates/ml-core/src/
mv crates/ml/src/training.rs crates/ml-core/src/
# Extracted shared items
mv crates/ml/src/mixed_precision.rs crates/ml-core/src/
mv crates/ml/src/xavier_init.rs crates/ml-core/src/
mv crates/ml/src/portfolio_tracker.rs crates/ml-core/src/
mv crates/ml/src/action_space.rs crates/ml-core/src/
mv crates/ml/src/order_router.rs crates/ml-core/src/
# Features and data
mv crates/ml/src/features crates/ml-core/src/
mv crates/ml/src/feature_cache.rs crates/ml-core/src/
mv crates/ml/src/preprocessing.rs crates/ml-core/src/
mv crates/ml/src/data_loader.rs crates/ml-core/src/
mv crates/ml/src/data_loaders crates/ml-core/src/
mv crates/ml/src/data_pipeline crates/ml-core/src/
mv crates/ml/src/data_validation crates/ml-core/src/
mv crates/ml/src/evaluation crates/ml-core/src/
# Metrics and monitoring
mv crates/ml/src/metrics crates/ml-core/src/
mv crates/ml/src/performance.rs crates/ml-core/src/
mv crates/ml/src/observability crates/ml-core/src/
Step 3: Update ml-core/src/lib.rs
Declare all moved modules with pub mod. Include all type definitions and re-exports. Copy the relevant use imports (serde, chrono, rust_decimal, etc.).
Step 4: Update all use crate:: imports in moved files
Every file in crates/ml-core/src/ that uses use crate:: — these references are now correct (they refer to ml-core's own modules). Verify no moved file imports something that stayed in ml.
Potential issues:
safety/imports fromcrate::dqn::(but mixed_precision is now in ml-core root)features/may import from model-specific modules → fix or feature-gatedata_loaders/importscrate::types::OHLCVBar→ still in ml-core ✓evaluation/importscrate::features::→ still in ml-core ✓training/unified_trainer.rs— verify it only imports items now in ml-corecheckpoint/— verify no model-specific imports
Run grep -rn 'use crate::dqn\|use crate::ppo\|use crate::tft\|use crate::mamba\|use crate::ensemble\|use crate::hyperopt\|use crate::trainers' crates/ml-core/src/ to find any imports of modules that are NOT in ml-core. These must be removed/refactored.
Step 5: Update ml/src/lib.rs
Replace removed pub mod declarations with re-exports:
// Add dependency
pub use ml_core;
// Re-export everything from ml-core
pub use ml_core::*;
// Explicitly re-export modules for path compatibility
pub use ml_core::common;
pub use ml_core::config;
pub use ml_core::checkpoint;
// ... etc for all modules that external consumers access by path (ml::checkpoint::X)
Step 6: Add ml-core dependency to ml/Cargo.toml
[dependencies]
ml-core = { workspace = true }
Step 7: Verify compilation
Run: SQLX_OFFLINE=true cargo check -p ml-core 2>&1 | tail -5
Expected: ml-core compiles
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
Expected: ml compiles (re-exports resolve)
Step 8: Fix any compilation errors
Iterate on import fixes until both ml-core and ml compile cleanly.
Step 9: Run tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Expected: All tests still pass
Step 10: Run clippy
Run: SQLX_OFFLINE=true cargo clippy -p ml-core -p ml -- -D warnings 2>&1 | tail -10
Expected: 0 errors, 0 warnings
Step 11: Commit
git add -A
git commit -m "refactor(ml): move core modules to ml-core crate
Move types, errors, traits, features, data loaders, checkpoint,
safety, GPU utils, and shared infrastructure to ml-core.
Re-export from ml facade for backward compatibility."
Phase 3: Build ml-rl (RL Models)
Task 6: Write ml-rl Cargo.toml
Files:
- Create:
crates/ml-rl/Cargo.toml
Step 1: Write Cargo.toml
Dependencies: ml-core + candle-core, candle-nn + RL-specific deps (crossbeam, etc.).
Feature flags:
[features]
default = ["cuda"]
cuda = ["ml-core/cuda"]
nccl = ["cuda"]
Step 2: Commit
Task 7: Move RL Modules to ml-rl
Files:
- Move:
crates/ml/src/dqn/→crates/ml-rl/src/dqn/ - Move:
crates/ml/src/ppo/→crates/ml-rl/src/ppo/ - Move:
crates/ml/src/cuda_pipeline/→crates/ml-rl/src/cuda_pipeline/ - Modify:
crates/ml-rl/src/lib.rs - Modify:
crates/ml/src/lib.rs
Step 1: Move modules
mv crates/ml/src/dqn crates/ml-rl/src/
mv crates/ml/src/ppo crates/ml-rl/src/
mv crates/ml/src/cuda_pipeline crates/ml-rl/src/
Step 2: Write ml-rl/src/lib.rs
// Same clippy attributes as ml-core
pub mod dqn;
pub mod ppo;
pub mod cuda_pipeline;
Step 3: Fix all imports in ml-rl
In every file under crates/ml-rl/src/:
use crate::MLError→use ml_core::MLErroruse crate::mixed_precision→use ml_core::mixed_precisionuse crate::xavier_init→use ml_core::xavier_inituse crate::portfolio_tracker→use ml_core::portfolio_trackeruse crate::action_space→use ml_core::action_spaceuse crate::order_router→use ml_core::order_routeruse crate::common::→use ml_core::common::use crate::cuda_compat::→use ml_core::cuda_compat::use crate::gradient_accumulation::→use ml_core::gradient_accumulation::use crate::training::unified_trainer::→use ml_core::training::unified_trainer::use crate::safety::→use ml_core::safety::use crate::tensor_ops::→use ml_core::tensor_ops::use crate::gpu::→use ml_core::gpu::use crate::checkpoint::→use ml_core::checkpoint::use crate::features::→use ml_core::features::use crate::evaluation::→use ml_core::evaluation::use crate::Adam→use ml_core::Adamuse crate::PRECISION_FACTOR→use ml_core::PRECISION_FACTORuse crate::{MLError, MLResult}→use ml_core::{MLError, MLResult}
Keep use crate::dqn:: and use crate::ppo:: as-is (these reference ml-rl's own modules).
Remove the re-exports from dqn/mod.rs added in Task 3 (they re-exported from crate:: which was ml, now those modules are in ml-core):
// REMOVE these from dqn/mod.rs:
// pub use crate::mixed_precision;
// pub use crate::xavier_init;
// etc.
// REPLACE WITH:
pub use ml_core::mixed_precision;
pub use ml_core::xavier_init;
pub use ml_core::portfolio_tracker;
pub use ml_core::action_space;
pub use ml_core::order_router;
Also fix PPO re-exports in ppo/mod.rs:
// ppo/circuit_breaker.rs re-exports from crate::common::circuit_breaker
// Change to: ml_core::common::circuit_breaker
Handle cross-RL deps:
- PPO imports
crate::dqn::circuit_breaker→ becomescrate::dqn::circuit_breaker(still works via dqn re-export) ORml_core::common::circuit_breaker(direct) - PPO imports
crate::dqn::mixed_precision::training_dtype→ml_core::mixed_precision::training_dtype - PPO imports
crate::dqn::portfolio_tracker→ml_core::portfolio_tracker - PPO imports
crate::dqn::xavier_init::linear_xavier→ml_core::xavier_init::linear_xavier - cuda_pipeline imports
crate::dqn::mixed_precision→ml_core::mixed_precision - cuda_pipeline imports
crate::dqn::replay_buffer_type::GpuBatch→crate::dqn::replay_buffer_type::GpuBatch(stays in ml-rl)
Watch for: use crate::trainers::DQNTrainer in dqn/ — this is a reverse dep. If it exists, it's likely in test code. If in non-test code, it needs to be removed/refactored (trainers will be in ml-infra).
Watch for: use crate::hyperopt::adapters::PPOTrainer in ppo/ — same issue. Check if test-only.
Step 4: Update ml/src/lib.rs
Add re-exports:
pub use ml_rl::dqn;
pub use ml_rl::ppo;
pub use ml_rl::cuda_pipeline;
Add dependency to ml/Cargo.toml:
ml-rl = { workspace = true }
Step 5: Verify compilation
Run: SQLX_OFFLINE=true cargo check -p ml-rl 2>&1 | tail -10
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -10
Step 6: Fix errors iteratively
Keep fixing imports until both compile.
Step 7: Run tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Step 8: Commit
git add -A
git commit -m "refactor(ml): move DQN, PPO, cuda_pipeline to ml-rl crate"
Phase 4: Build ml-supervised (Supervised Models)
Task 8: Write ml-supervised Cargo.toml
Files:
- Create:
crates/ml-supervised/Cargo.toml
Dependencies: ml-core + candle-core, candle-nn.
Feature flags:
[features]
default = ["cuda"]
cuda = ["ml-core/cuda"]
Step 1: Commit
Task 9: Move Supervised Models to ml-supervised
Files:
- Move:
crates/ml/src/tft/→crates/ml-supervised/src/tft/ - Move:
crates/ml/src/mamba/→crates/ml-supervised/src/mamba/ - Move:
crates/ml/src/liquid/→crates/ml-supervised/src/liquid/ - Move:
crates/ml/src/tgnn/→crates/ml-supervised/src/tgnn/ - Move:
crates/ml/src/tlob/→crates/ml-supervised/src/tlob/ - Move:
crates/ml/src/kan/→crates/ml-supervised/src/kan/ - Move:
crates/ml/src/xlstm/→crates/ml-supervised/src/xlstm/ - Move:
crates/ml/src/diffusion/→crates/ml-supervised/src/diffusion/ - Move:
crates/ml/src/transformers/→crates/ml-supervised/src/transformers/ - Move:
crates/ml/src/flash_attention/→crates/ml-supervised/src/flash_attention/ - Modify:
crates/ml-supervised/src/lib.rs - Modify:
crates/ml/src/lib.rs
Step 1: Move modules
for mod in tft mamba liquid tgnn tlob kan xlstm diffusion transformers flash_attention; do
mv crates/ml/src/$mod crates/ml-supervised/src/
done
Step 2: Write ml-supervised/src/lib.rs
pub mod tft;
pub mod mamba;
pub mod liquid;
pub mod tgnn;
pub mod tlob;
pub mod kan;
pub mod xlstm;
pub mod diffusion;
pub mod transformers;
pub mod flash_attention;
Step 3: Fix all imports
Same pattern as Task 7: use crate::X → use ml_core::X for anything from ml-core.
Specific cross-model deps to handle:
tftimportscrate::liquid::FixedPoint→crate::liquid::FixedPoint(both in ml-supervised ✓)mambaimportscrate::liquid::FixedPoint→crate::liquid::FixedPoint(both in ml-supervised ✓)tftimportscrate::inference::RealInferenceError→ This module stays in ml facade! Need to either:- Move
RealInferenceErrortype to ml-core, OR - Remove this import if it's only used in a few places and can be refactored
- Move
- All models import
crate::dqn::mixed_precision::training_dtype→ml_core::mixed_precision::training_dtype - All models import
crate::training::unified_trainer::*→ml_core::training::unified_trainer::*
Step 4: Update ml/src/lib.rs
pub use ml_supervised::tft;
pub use ml_supervised::mamba;
pub use ml_supervised::liquid;
pub use ml_supervised::tgnn;
pub use ml_supervised::tlob;
pub use ml_supervised::kan;
pub use ml_supervised::xlstm;
pub use ml_supervised::diffusion;
pub use ml_supervised::transformers;
pub use ml_supervised::flash_attention;
Add dependency: ml-supervised = { workspace = true }
Step 5: Verify and fix
Run: SQLX_OFFLINE=true cargo check -p ml-supervised 2>&1 | tail -10
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -10
Step 6: Run tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Step 7: Commit
git add -A
git commit -m "refactor(ml): move 8 supervised models to ml-supervised crate
TFT, Mamba, Liquid, TGNN, TLOB, KAN, xLSTM, Diffusion plus shared
transformers and flash_attention infrastructure."
Phase 5: Build ml-infra (Training Infrastructure)
Task 10: Write ml-infra Cargo.toml
Files:
- Create:
crates/ml-infra/Cargo.toml
Dependencies: ml-core, ml-rl, ml-supervised + argmin (for hyperopt), model-specific deps.
Feature flags:
[features]
default = ["cuda"]
cuda = ["ml-core/cuda", "ml-rl/cuda", "ml-supervised/cuda"]
Step 1: Commit
Task 11: Move Infrastructure Modules to ml-infra
Files:
- Move:
crates/ml/src/hyperopt/→crates/ml-infra/src/hyperopt/ - Move:
crates/ml/src/ensemble/→crates/ml-infra/src/ensemble/ - Move:
crates/ml/src/trainers/→crates/ml-infra/src/trainers/ - Move:
crates/ml/src/benchmark/→crates/ml-infra/src/benchmark/ - Move:
crates/ml/src/deployment/→crates/ml-infra/src/deployment/ - Move:
crates/ml/src/training_pipeline.rs→crates/ml-infra/src/training_pipeline.rs - Move:
crates/ml/src/walk_forward.rs→crates/ml-infra/src/walk_forward.rs - Modify:
crates/ml-infra/src/lib.rs - Modify:
crates/ml/src/lib.rs
Step 1: Move modules
for mod in hyperopt ensemble trainers benchmark deployment; do
mv crates/ml/src/$mod crates/ml-infra/src/
done
mv crates/ml/src/training_pipeline.rs crates/ml-infra/src/
mv crates/ml/src/walk_forward.rs crates/ml-infra/src/
Step 2: Write ml-infra/src/lib.rs
pub mod hyperopt;
pub mod ensemble;
pub mod trainers;
pub mod benchmark;
pub mod deployment;
pub mod training_pipeline;
pub mod walk_forward;
Step 3: Fix all imports
This is the most complex crate — it imports from all three sub-crates:
use crate::dqn::DQN→use ml_rl::dqn::DQNuse crate::dqn::DQNConfig→use ml_rl::dqn::DQNConfiguse crate::ppo::PPO→use ml_rl::ppo::PPOuse crate::tft::*→use ml_supervised::tft::*use crate::mamba::*→use ml_supervised::mamba::*use crate::liquid::*→use ml_supervised::liquid::*use crate::diffusion::*→use ml_supervised::diffusion::*use crate::kan::*→use ml_supervised::kan::*use crate::xlstm::*→use ml_supervised::xlstm::*use crate::tgnn::*→use ml_supervised::tgnn::*use crate::tlob::*→use ml_supervised::tlob::*use crate::cuda_pipeline::*→use ml_rl::cuda_pipeline::*- All shared items:
use crate::X→use ml_core::X
Step 4: Update ml/src/lib.rs
pub use ml_infra::hyperopt;
pub use ml_infra::ensemble;
pub use ml_infra::trainers;
pub use ml_infra::benchmark;
pub use ml_infra::deployment;
pub use ml_infra::training_pipeline;
pub use ml_infra::walk_forward;
Add dependency: ml-infra = { workspace = true }
Step 5: Verify and fix
Run: SQLX_OFFLINE=true cargo check -p ml-infra 2>&1 | tail -10
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -10
Step 6: Run tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Step 7: Commit
git add -A
git commit -m "refactor(ml): move hyperopt, ensemble, trainers to ml-infra crate"
Phase 6: Finalize Facade and Verify
Task 12: Clean Up ml Facade
Files:
- Modify:
crates/ml/src/lib.rs— final cleanup - Modify:
crates/ml/Cargo.toml— update dependencies
Step 1: Update ml/Cargo.toml
- Add:
ml-core,ml-rl,ml-supervised,ml-infraas dependencies - Remove: all dependencies that are now only used by sub-crates
- Keep: dependencies used by remaining facade modules (
inference.rs,validation/,risk/, etc.)
Step 2: Verify ml/src/lib.rs has complete re-exports
Every module path that external consumers use (e.g., ml::dqn::DQNConfig, ml::ensemble::EnsembleCoordinator) must resolve. Create a checklist from the external consumer import scan (Task 1 research).
Step 3: Fix remaining facade module imports
Modules still in ml facade (inference.rs, validation/, risk/, regime/, etc.) need import updates:
use crate::dqn::— these now come fromml_rlvia re-export, souse crate::dqn::still works ✓use crate::tft::— same via re-export fromml_supervised✓use crate::ensemble::— same via re-export fromml_infra✓use crate::MLError— fromml_coreviapub use ml_core::*✓
This should work because the facade re-exports everything. But verify with compilation.
Step 4: Verify compilation
Run: SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
Step 5: Commit
git add -A
git commit -m "refactor(ml): finalize facade with complete re-exports"
Task 13: Full Workspace Verification
Files: None modified
Step 1: Full workspace check
Run: SQLX_OFFLINE=true cargo check --workspace 2>&1 | tail -10
Expected: 0 errors across all workspace members
Step 2: Full workspace clippy
Run: SQLX_OFFLINE=true cargo clippy --workspace -- -D warnings 2>&1 | tail -20
Expected: 0 errors, 0 warnings
Step 3: Run ml tests
Run: SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
Expected: Same test count as baseline (2506+), 0 failures
Step 4: Run sub-crate tests
Run each in parallel:
SQLX_OFFLINE=true cargo test -p ml-core --lib 2>&1 | tail -5
SQLX_OFFLINE=true cargo test -p ml-rl --lib 2>&1 | tail -5
SQLX_OFFLINE=true cargo test -p ml-supervised --lib 2>&1 | tail -5
SQLX_OFFLINE=true cargo test -p ml-infra --lib 2>&1 | tail -5
Expected: Tests distributed across sub-crates, total matches baseline
Step 5: Run downstream service checks
Run:
SQLX_OFFLINE=true cargo check -p trading_service 2>&1 | tail -3
SQLX_OFFLINE=true cargo check -p ml_training_service 2>&1 | tail -3
SQLX_OFFLINE=true cargo check -p backtesting_service 2>&1 | tail -3
SQLX_OFFLINE=true cargo check -p trading_agent_service 2>&1 | tail -3
Expected: All compile with 0 errors (they use ml facade, re-exports preserve paths)
Step 6: Verify compile time improvement
Run: SQLX_OFFLINE=true cargo build -p ml --timings 2>&1 | tail -5
Open the timings HTML report. Compare per-crate times against the baseline 55.1s.
Step 7: Commit if any fixes were needed
Task 14: Update common dev-dependency
Files:
- Modify:
crates/common/Cargo.toml
Step 1: Update dev-dependency
common has ml = { path = "../ml" } as a dev-dependency. Update the path since ml is still at the same location:
ml = { path = "../ml" } # Should still work — verify
If paths changed, update accordingly.
Step 2: Verify
Run: SQLX_OFFLINE=true cargo test -p common --lib 2>&1 | tail -5
Step 3: Commit if changed
Task 15: Update Memory and Documentation
Files:
- Modify:
/home/jgrusewski/.claude/projects/-home-jgrusewski-Work-foxhunt/memory/MEMORY.md
Step 1: Update MEMORY.md
Update the Architecture section to reflect the new 5-crate ML structure. Update the ML Model Training section with new crate paths. Remove any stale references to crates/ml/src/dqn/mixed_precision.rs etc.
Step 2: Final commit
git add -A
git commit -m "refactor(ml): complete crate split — 5 crates, parallel compilation
Split the monolithic ml crate (260K lines, 55s compile) into:
- ml-core: shared types, traits, features, data, checkpoint, safety
- ml-rl: DQN + PPO + cuda_pipeline
- ml-supervised: TFT, Mamba, Liquid, TGNN, TLOB, KAN, xLSTM, Diffusion
- ml-infra: hyperopt, ensemble, trainers, benchmark, deployment
- ml: thin facade re-exporting everything
Zero API changes for downstream consumers.
Incremental rebuild after model edit: ~55s → ~10-15s."
Execution Checklist
| Task | Description | Est. Size | Depends On |
|---|---|---|---|
| 1 | Verify clean baseline | verify | — |
| 2 | Create sub-crate dirs + workspace | scaffold | 1 |
| 3 | Extract shared items from dqn/ | refactor | 2 |
| 4 | Write ml-core Cargo.toml | config | 2 |
| 5 | Move core modules to ml-core | large | 3, 4 |
| 6 | Write ml-rl Cargo.toml | config | 4 |
| 7 | Move RL modules to ml-rl | large | 5, 6 |
| 8 | Write ml-supervised Cargo.toml | config | 4 |
| 9 | Move supervised models | large | 5, 8 |
| 10 | Write ml-infra Cargo.toml | config | 6, 8 |
| 11 | Move infra modules | large | 7, 9, 10 |
| 12 | Clean up ml facade | medium | 11 |
| 13 | Full verification | verify | 12 |
| 14 | Update common dev-dep | small | 12 |
| 15 | Update memory + final commit | small | 13 |
Critical Invariants (Verify After Every Task)
- No stubs: Every function must be wired to its real implementation
- No lost code: Every module in the inventory must be accounted for
- No API changes:
use ml::X::Ymust work for all external consumers - Tests pass: Same test count, 0 failures
- Clippy clean: 0 errors, 0 warnings
- Feature flags work:
--features cuda,--no-default-features,--features financialall compile