# 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 6 crates that compile in parallel, reducing incremental rebuilds from 55s to ~6-12s. **Architecture:** 5 sub-crates (`ml-core`, `ml-dqn`, `ml-ppo`, `ml-supervised`, `ml-infra`) + thin `ml` facade. DQN, PPO, and supervised models compile in 3-way parallel. 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-dqn/Cargo.toml` - Create: `crates/ml-dqn/src/lib.rs` - Create: `crates/ml-ppo/Cargo.toml` - Create: `crates/ml-ppo/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** ```bash mkdir -p crates/ml-core/src crates/ml-dqn/src crates/ml-ppo/src crates/ml-supervised/src crates/ml-infra/src ``` **Step 2: Add workspace members** In root `Cargo.toml`, add to `[workspace] members`: ```toml "crates/ml-core", "crates/ml-dqn", "crates/ml-ppo", "crates/ml-supervised", "crates/ml-infra", ``` And add workspace dependency entries: ```toml ml-core = { path = "crates/ml-core" } ml-dqn = { path = "crates/ml-dqn" } ml-ppo = { path = "crates/ml-ppo" } 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-core` as dependency for `ml-dqn`, `ml-ppo`, `ml-supervised`, `ml-infra` See the detailed Cargo.toml specs in Tasks 4-10. **Step 4: Create stub lib.rs for each** Each gets an empty `pub mod` list initially: ```rust // 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** ```bash git add crates/ml-core crates/ml-dqn crates/ml-ppo 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`. Also extract `TradingAction` from `dqn/agent.rs` to enable DQN/PPO independence. **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/agent.rs` — move `TradingAction` enum to new file - Create: `crates/ml/src/trading_action.rs` — `TradingAction` enum (Buy/Sell/Hold) - Modify: `crates/ml/src/dqn/mod.rs` — replace module declarations with re-exports - Modify: `crates/ml/src/lib.rs` — add `pub mod` for new top-level modules - Modify: All files importing these via `crate::dqn::*` path **Step 1: Move files** ```bash 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: Extract TradingAction from dqn/agent.rs** Create `crates/ml/src/trading_action.rs` with the `TradingAction` enum (copied from `dqn/agent.rs`). In `dqn/agent.rs`, replace the enum with `pub use crate::trading_action::TradingAction;`. This is the only PPO→DQN dependency remaining after the other extractions — making it shared enables full DQN/PPO independence. **Step 3: Update dqn/mod.rs** Replace the old `pub mod` declarations with re-exports so existing `crate::dqn::X` paths still work: ```rust // 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; pub use crate::trading_action::TradingAction; ``` **Step 4: Add modules to ml/lib.rs** Add these lines to `lib.rs`: ```rust pub mod mixed_precision; pub mod xavier_init; pub mod portfolio_tracker; pub mod action_space; pub mod order_router; pub mod trading_action; ``` **Step 5: Fix internal imports in moved files** In each moved file, change `use crate::dqn::` imports to `use crate::` where referencing peer modules. Specific fixes needed: - `action_space.rs`: has no `crate::dqn::` imports (only std/serde) — no changes needed - `xavier_init.rs`: uses `candle_core`/`candle_nn` only — no changes needed - `mixed_precision.rs`: uses `candle_core` only — no changes needed - `portfolio_tracker.rs`: check for `crate::dqn::` imports and fix - `order_router.rs`: imports `crate::dqn::action_space::*` → change to `crate::action_space::*`; imports `crate::common::action::*` → keep as-is - PPO test files using `crate::dqn::TradingAction` → change to `crate::trading_action::TradingAction` **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** ```bash 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: ```toml [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** ```bash 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/` to `crates/ml-core/src/` - Modify: `crates/ml-core/src/lib.rs` — declare all modules - Modify: `crates/ml/src/lib.rs` — remove moved modules, add `pub 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** ```bash # 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 from `crate::dqn::` (but mixed_precision is now in ml-core root) - `features/` may import from model-specific modules → fix or feature-gate - `data_loaders/` imports `crate::types::OHLCVBar` → still in ml-core ✓ - `evaluation/` imports `crate::features::` → still in ml-core ✓ - `training/unified_trainer.rs` — verify it only imports items now in ml-core - `checkpoint/` — 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: ```rust // 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** ```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** ```bash 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-dqn and ml-ppo (RL Models — Separate Crates) ### Task 6: Write ml-dqn Cargo.toml **Files:** - Create: `crates/ml-dqn/Cargo.toml` **Step 1: Write Cargo.toml** Dependencies: `ml-core` + `candle-core`, `candle-nn` + DQN-specific deps (`crossbeam`, etc.). Feature flags: ```toml [features] default = ["cuda"] cuda = ["ml-core/cuda"] nccl = ["cuda"] ``` **Step 2: Commit** --- ### Task 7a: Move DQN + cuda_pipeline to ml-dqn **Files:** - Move: `crates/ml/src/dqn/` → `crates/ml-dqn/src/dqn/` - Move: `crates/ml/src/cuda_pipeline/` → `crates/ml-dqn/src/cuda_pipeline/` - Modify: `crates/ml-dqn/src/lib.rs` - Modify: `crates/ml/src/lib.rs` **Step 1: Move modules** ```bash mv crates/ml/src/dqn crates/ml-dqn/src/ mv crates/ml/src/cuda_pipeline crates/ml-dqn/src/ ``` **Step 2: Write ml-dqn/src/lib.rs** ```rust // Same clippy attributes as ml-core pub mod dqn; pub mod cuda_pipeline; ``` **Step 3: Fix all imports in ml-dqn** In every file under `crates/ml-dqn/src/`: - `use crate::MLError` → `use ml_core::MLError` - `use crate::mixed_precision` → `use ml_core::mixed_precision` - `use crate::xavier_init` → `use ml_core::xavier_init` - `use crate::portfolio_tracker` → `use ml_core::portfolio_tracker` - `use crate::action_space` → `use ml_core::action_space` - `use crate::order_router` → `use ml_core::order_router` - `use crate::trading_action` → `use ml_core::trading_action` - `use 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::Adam` - `use crate::PRECISION_FACTOR` → `use ml_core::PRECISION_FACTOR` - `use crate::{MLError, MLResult}` → `use ml_core::{MLError, MLResult}` Keep `use crate::dqn::` as-is (references ml-dqn's own dqn module). Keep `use crate::cuda_pipeline::` as-is (references ml-dqn's own cuda_pipeline module). Update the re-exports from `dqn/mod.rs` added in Task 3: ```rust // REPLACE crate:: references WITH ml_core:: 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; pub use ml_core::trading_action::TradingAction; ``` cuda_pipeline imports: - `crate::dqn::mixed_precision` → `ml_core::mixed_precision` - `crate::dqn::replay_buffer_type::GpuBatch` → `crate::dqn::replay_buffer_type::GpuBatch` (stays in ml-dqn ✓) Watch for: `use crate::trainers::DQNTrainer` in dqn/ — reverse dep, likely test-only. Remove or cfg(test) gate with a comment. **Step 4: Update ml/src/lib.rs** Add re-exports: ```rust pub use ml_dqn::dqn; pub use ml_dqn::cuda_pipeline; ``` Add dependency to `ml/Cargo.toml`: ```toml ml-dqn = { workspace = true } ``` **Step 5: Verify compilation** Run: `SQLX_OFFLINE=true cargo check -p ml-dqn 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** ```bash git add -A git commit -m "refactor(ml): move DQN + cuda_pipeline to ml-dqn crate" ``` --- ### Task 7b: Write ml-ppo Cargo.toml and Move PPO **Files:** - Create: `crates/ml-ppo/Cargo.toml` - Move: `crates/ml/src/ppo/` → `crates/ml-ppo/src/ppo/` - Modify: `crates/ml-ppo/src/lib.rs` - Modify: `crates/ml/src/lib.rs` **Step 1: Write ml-ppo Cargo.toml** Dependencies: `ml-core` + `candle-core`, `candle-nn`. NO dependency on `ml-dqn`. Feature flags: ```toml [features] default = ["cuda"] cuda = ["ml-core/cuda"] ``` **Step 2: Move PPO** ```bash mv crates/ml/src/ppo crates/ml-ppo/src/ ``` **Step 3: Write ml-ppo/src/lib.rs** ```rust // Same clippy attributes as ml-core pub mod ppo; ``` **Step 4: Fix all imports in ml-ppo** Same pattern as ml-dqn: `use crate::X` → `use ml_core::X` for all shared items. Key changes: - `use crate::dqn::circuit_breaker` → `use ml_core::common::circuit_breaker` (direct path, no dqn dependency) - `use crate::dqn::mixed_precision::training_dtype` → `use ml_core::mixed_precision::training_dtype` - `use crate::dqn::portfolio_tracker` → `use ml_core::portfolio_tracker` - `use crate::dqn::xavier_init::linear_xavier` → `use ml_core::xavier_init::linear_xavier` - `use crate::dqn::TradingAction` → `use ml_core::trading_action::TradingAction` (test-only) Fix `ppo/circuit_breaker.rs`: ```rust // Change: pub use crate::common::circuit_breaker::* // To: pub use ml_core::common::circuit_breaker::* ``` Watch for: `use crate::hyperopt::adapters::PPOTrainer` in ppo/ — reverse dep, likely test-only. **Step 5: Update ml/src/lib.rs** ```rust pub use ml_ppo::ppo; ``` Add dependency: `ml-ppo = { workspace = true }` **Step 6: Verify compilation** Run: `SQLX_OFFLINE=true cargo check -p ml-ppo 2>&1 | tail -10` Run: `SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -10` **Step 7: Verify DQN and PPO are independent** Run: `SQLX_OFFLINE=true cargo tree -p ml-ppo --depth 1 | grep ml-dqn` Expected: NO output (ml-ppo must NOT depend on ml-dqn) **Step 8: Run tests** Run: `SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5` **Step 9: Commit** ```bash git add -A git commit -m "refactor(ml): move PPO to ml-ppo crate (independent of ml-dqn)" ``` --- ## 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: ```toml [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** ```bash 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** ```rust 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: - `tft` imports `crate::liquid::FixedPoint` → `crate::liquid::FixedPoint` (both in ml-supervised ✓) - `mamba` imports `crate::liquid::FixedPoint` → `crate::liquid::FixedPoint` (both in ml-supervised ✓) - `tft` imports `crate::inference::RealInferenceError` → This module stays in ml facade! Need to either: - Move `RealInferenceError` type to ml-core, OR - Remove this import if it's only used in a few places and can be refactored - 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** ```rust 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** ```bash 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-dqn`, `ml-ppo`, `ml-supervised` + `argmin` (for hyperopt), model-specific deps. Feature flags: ```toml [features] default = ["cuda"] cuda = ["ml-core/cuda", "ml-dqn/cuda", "ml-ppo/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** ```bash 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** ```rust 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 four model sub-crates: - `use crate::dqn::DQN` → `use ml_dqn::dqn::DQN` - `use crate::dqn::DQNConfig` → `use ml_dqn::dqn::DQNConfig` - `use crate::ppo::PPO` → `use ml_ppo::ppo::PPO` - `use crate::cuda_pipeline::*` → `use ml_dqn::cuda_pipeline::*` - `use 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::*` - All shared items: `use crate::X` → `use ml_core::X` **Step 4: Update ml/src/lib.rs** ```rust 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** ```bash 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-dqn`, `ml-ppo`, `ml-supervised`, `ml-infra` as 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 from `ml_dqn` via re-export, so `use crate::dqn::` still works ✓ - `use crate::ppo::` — same via re-export from `ml_ppo` ✓ - `use crate::tft::` — same via re-export from `ml_supervised` ✓ - `use crate::ensemble::` — same via re-export from `ml_infra` ✓ - `use crate::MLError` — from `ml_core` via `pub 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** ```bash 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: ```bash SQLX_OFFLINE=true cargo test -p ml-core --lib 2>&1 | tail -5 SQLX_OFFLINE=true cargo test -p ml-dqn --lib 2>&1 | tail -5 SQLX_OFFLINE=true cargo test -p ml-ppo --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: ```bash 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: ```toml 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 6-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** ```bash git add -A git commit -m "refactor(ml): complete crate split — 6 crates, 3-way parallel compilation Split the monolithic ml crate (260K lines, 55s compile) into: - ml-core: shared types, traits, features, data, checkpoint, safety - ml-dqn: DQN + cuda_pipeline - ml-ppo: PPO (independent of ml-dqn) - ml-supervised: TFT, Mamba, Liquid, TGNN, TLOB, KAN, xLSTM, Diffusion - ml-infra: hyperopt, ensemble, trainers, benchmark, deployment - ml: thin facade re-exporting everything 3-way parallel compilation (ml-dqn + ml-ppo + ml-supervised). Zero API changes for downstream consumers. Incremental rebuild after model edit: ~55s → ~6-12s." ``` --- ## 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/ + TradingAction | refactor | 2 | | 4 | Write ml-core Cargo.toml | config | 2 | | 5 | Move core modules to ml-core | **large** | 3, 4 | | 6 | Write ml-dqn Cargo.toml | config | 4 | | 7a | Move DQN + cuda_pipeline to ml-dqn | **large** | 5, 6 | | 7b | Write ml-ppo Cargo.toml + move PPO | **large** | 5 | | 8 | Write ml-supervised Cargo.toml | config | 4 | | 9 | Move supervised models | **large** | 5, 8 | | 10 | Write ml-infra Cargo.toml | config | 6, 7b, 8 | | 11 | Move infra modules | **large** | 7a, 7b, 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 | Note: Tasks 7a, 7b, and 9 can execute in parallel (they move independent module sets). ## Critical Invariants (Verify After Every Task) 1. **No stubs**: Every function must be wired to its real implementation 2. **No lost code**: Every module in the inventory must be accounted for 3. **No API changes**: `use ml::X::Y` must work for all external consumers 4. **Tests pass**: Same test count, 0 failures 5. **Clippy clean**: 0 errors, 0 warnings 6. **Feature flags work**: `--features cuda`, `--no-default-features`, `--features financial` all compile