Restore 45-action factored space via Branching DQN (Tavakoli 2018), outputting 11 Q-values (5+3+3) instead of 45. This was reduced to 5 exposure-only actions during debugging and was never intended as permanent. - Enable use_branching: true by default in DQNConfig and DQNHyperparameters - Add branching paths to select_action_with_confidence and select_action_inference - Update agent.rs select_action_factored for branching-aware selection - Expand CountBonus to per-branch tracking with bonuses_branched() - Add order_type + urgency distribution tracking in monitoring - Add DQN_ORDER_ACTIONS=3, DQN_URGENCY_ACTIONS=3, DQN_TOTAL_ACTIONS=45 to CUDA header - Fix 7 pre-existing clippy doc_markdown errors in regime_conditional.rs - Fix pre-existing cognitive_complexity in replay_buffer_type.rs (extract helpers) - Fix flaky GPU test OOM under parallel execution (CPU fallback + test VRAM safety) - Delete unused flash_attention submodules (block_sparse, causal_masking, etc.) - Add GPU hot-path guard scripts and ensemble/hyperopt adapter improvements Tests: ml-dqn 416/0, ml 905/0, clippy 0 errors on both crates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
706 lines
27 KiB
Markdown
706 lines
27 KiB
Markdown
# Forward-Port Main onto ML Crate Split Branch — Implementation Plan
|
|
|
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
|
|
**Goal:** Port 24 commits of GPU performance work from `main` onto `feature/ml-crate-split-phase2`, adapting file paths to the new sub-crate layout.
|
|
|
|
**Architecture:** Cherry-pick + path-rewrite in 8 phases. Commits that only touch sub-crates (`ml-core`, `ml-dqn`, etc.) or infra files apply directly. Commits that touch `crates/ml/` files which were moved to sub-crates need path-rewritten patches. Deleted files (parquet, smoke_tests) are triaged. Compiler-driven fixup after each phase.
|
|
|
|
**Tech Stack:** Rust workspace, git format-patch/apply, sed path rewriting, `SQLX_OFFLINE=true cargo check --workspace`
|
|
|
|
**Worktree:** `.worktrees/ml-split-p2` on branch `feature/ml-crate-split-phase2`
|
|
|
|
**Build command:** `SQLX_OFFLINE=true cargo check --workspace`
|
|
**Test command:** `SQLX_OFFLINE=true cargo test -p <crate> --lib`
|
|
**Clippy:** `SQLX_OFFLINE=true cargo clippy --workspace -- -D warnings`
|
|
|
|
---
|
|
|
|
## File Move Mapping (Branch Reality)
|
|
|
|
These files were moved from `crates/ml/src/` to sub-crates on the branch. Main modified them at their OLD paths. Patches must target the NEW paths.
|
|
|
|
```
|
|
OLD PATH (on main) → NEW PATH (on branch)
|
|
─────────────────────────────────────────────────────────────────────────
|
|
crates/ml/src/cuda_pipeline/* → crates/ml-core/src/cuda_pipeline/*
|
|
crates/ml/src/features/extraction.rs → crates/ml-features/src/extraction.rs
|
|
crates/ml/src/features/production_adapter.rs → crates/ml-features/src/production_adapter.rs
|
|
crates/ml/src/features/unified.rs → crates/ml-features/src/unified.rs
|
|
crates/ml/src/features/mod.rs → crates/ml-features/src/lib.rs (merged into)
|
|
crates/ml/src/trainers/dqn/trainer.rs → crates/ml-dqn/src/trainer/trainer.rs
|
|
crates/ml/src/trainers/dqn/config.rs → crates/ml-dqn/src/trainer/config.rs
|
|
crates/ml/src/trainers/dqn/data_loading.rs → crates/ml-dqn/src/trainer/data_loading.rs
|
|
crates/ml/src/trainers/dqn/features.rs → crates/ml-dqn/src/trainer/features.rs
|
|
crates/ml/src/trainers/dqn/mod.rs → crates/ml-dqn/src/trainer/mod.rs
|
|
crates/ml/src/trainers/dqn/monitoring.rs → crates/ml-dqn/src/trainer/monitoring.rs
|
|
crates/ml/src/trainers/ppo.rs → crates/ml-ppo/src/trainer.rs
|
|
crates/ml/src/hyperopt/adapters/dqn.rs → crates/ml-hyperopt/src/adapters/dqn.rs
|
|
crates/ml/src/hyperopt/adapters/ppo.rs → crates/ml-hyperopt/src/adapters/ppo.rs
|
|
crates/ml/src/hyperopt/adapters/continuous_ppo.rs → crates/ml-hyperopt/src/adapters/continuous_ppo.rs
|
|
crates/ml/src/hyperopt/adapters/mamba2.rs → crates/ml-hyperopt/src/adapters/mamba2.rs
|
|
crates/ml/src/hyperopt/shared_data.rs → crates/ml-hyperopt/src/shared_data.rs
|
|
crates/ml/src/ensemble/model_adapter.rs → crates/ml-ensemble/src/model_adapter.rs
|
|
|
|
STILL IN crates/ml/ (no rewrite needed):
|
|
src/data_loaders/*, src/walk_forward.rs, src/hyperopt/adapters/tft.rs,
|
|
examples/*, tests/*, Cargo.toml
|
|
|
|
DELETED on branch (main's changes are OBSOLETE):
|
|
src/data_loaders/parquet_utils.rs — branch intentionally removed all parquet code
|
|
src/feature_cache.rs — branch deleted (superseded by ml-features)
|
|
src/trainers/tft_parquet.rs — branch deleted (parquet removal)
|
|
src/trainers/dqn/smoke_tests/* — branch deleted entire directory (5 files, ~900 LOC)
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 0: Preparation
|
|
|
|
### Task 0a: Create backup tag
|
|
|
|
**Step 1:** Tag current branch state
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git tag backup/ml-split-p2-before-forward-port
|
|
```
|
|
|
|
**Step 2:** Verify clean working tree
|
|
|
|
```bash
|
|
git status
|
|
```
|
|
|
|
Expected: nothing to commit, working tree clean
|
|
|
|
**Step 3:** Record baseline test counts
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo test --workspace --lib 2>&1 | grep "test result" | sort
|
|
```
|
|
|
|
Save output for comparison after all phases.
|
|
|
|
---
|
|
|
|
## Phase 1: Infrastructure-Only Commits (3 commits, clean cherry-pick)
|
|
|
|
These commits touch only `infra/` files — no `crates/` conflicts at all.
|
|
|
|
### Task 1a: Cherry-pick infra commits
|
|
|
|
**Commits:**
|
|
- `47d49595` fix(train): correct --output to --output-dir arg, add Prometheus annotations
|
|
- `9d6a04ab` fix(grafana): add 20 missing metric panels to training dashboard
|
|
- `356f1d29` fix(train): remove duplicate annotations block from rebase artifact
|
|
|
|
**Step 1:** Cherry-pick all three (oldest first)
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git cherry-pick 47d49595 9d6a04ab 356f1d29
|
|
```
|
|
|
|
Expected: clean apply, no conflicts.
|
|
|
|
**Step 2:** Verify
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
```
|
|
|
|
**Step 3:** If any conflict: resolve, `git add`, `git cherry-pick --continue`
|
|
|
|
---
|
|
|
|
## Phase 2: Sub-Crate-Only Commits (5 commits, clean cherry-pick)
|
|
|
|
These commits ONLY modify files inside `crates/ml-core/`, `crates/ml-dqn/`, `crates/ml-ppo/`, or `crates/common/` — files that exist at the same paths on both branches.
|
|
|
|
### Task 2a: Cherry-pick sub-crate performance commits
|
|
|
|
**Commits (chronological):**
|
|
- `0355fb17` perf(metrics): expose step-level DQN metrics to Prometheus gauges
|
|
- `db65eb56` perf(gpu): eliminate GPU→CPU sync barriers from training hot path
|
|
- `ee12f1d9` perf(gpu): zero-sync gradient clipping — eliminate all GPU→CPU barriers
|
|
- `379c0bee` fix(dqn): cast F32 constants to input dtype for BF16 mixed precision on H100
|
|
- `1b9f09fc` perf(dqn): eliminate GPU→CPU roundtrip in branching action decomposition
|
|
|
|
**Step 1:** Cherry-pick all five
|
|
|
|
```bash
|
|
git cherry-pick 0355fb17 db65eb56 ee12f1d9 379c0bee 1b9f09fc
|
|
```
|
|
|
|
**Step 2:** If `1b9f09fc` fails (branching.rs may not exist yet — it's added by `89c3fb89` which comes in Phase 5): skip it for now, cherry-pick it after Phase 5.
|
|
|
|
```bash
|
|
git cherry-pick --abort # if it failed
|
|
# We'll retry 1b9f09fc after Phase 5
|
|
```
|
|
|
|
**Step 3:** Verify
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
```
|
|
|
|
**Step 4:** Commit checkpoint message if needed
|
|
|
|
---
|
|
|
|
## Phase 3: Mixed Commits — Sub-Crate + Simple ML Path Rewrites (7 commits)
|
|
|
|
These commits touch sub-crate files (apply cleanly) PLUS `crates/ml/` files that were moved. Strategy: cherry-pick, let sub-crate parts apply, then manually fix the `crates/ml/` parts using path-rewritten patches.
|
|
|
|
### Task 3a: GPU PER hot path (`e35ead5f`)
|
|
|
|
**Main's changes:** ml-dqn/dqn.rs, ml-dqn/quantile_regression.rs (clean), + `ml/src/cuda_pipeline/gpu_experience_collector.rs` (→ ml-core), `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer), `ml/src/trainers/dqn/trainer.rs` (→ ml-dqn/trainer)
|
|
|
|
**Step 1:** Generate and rewrite patch
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 e35ead5f --stdout > /tmp/e35ead5f.patch
|
|
|
|
# Rewrite moved file paths
|
|
sed -i 's|a/crates/ml/src/cuda_pipeline/|a/crates/ml-core/src/cuda_pipeline/|g' /tmp/e35ead5f.patch
|
|
sed -i 's|b/crates/ml/src/cuda_pipeline/|b/crates/ml-core/src/cuda_pipeline/|g' /tmp/e35ead5f.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/e35ead5f.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/e35ead5f.patch
|
|
```
|
|
|
|
**Step 2:** Apply with reject mode
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/e35ead5f.patch
|
|
```
|
|
|
|
**Step 3:** Resolve any `.rej` files. Check for `use crate::` paths that need updating:
|
|
- In ml-core files: `use crate::` is already correct (they're in ml-core)
|
|
- In ml-dqn/trainer files: `use crate::cuda_pipeline::` → `use ml_core::cuda_pipeline::`
|
|
|
|
**Step 4:** Compiler-driven fixup
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check -p ml-core -p ml-dqn
|
|
```
|
|
|
|
Fix any remaining import errors.
|
|
|
|
**Step 5:** Commit
|
|
|
|
```bash
|
|
git add -A
|
|
git commit -m "forward-port(e35ead5f): wire GPU PER into hot path (path-adapted)"
|
|
```
|
|
|
|
### Task 3b: IQN GPU PER weights + CUDA default (`b616d024`)
|
|
|
|
**Main's changes:** 10 sub-crate Cargo.tomls (cuda default feature) + `ml/Cargo.toml` + `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer)
|
|
|
|
**Step 1:** Generate and rewrite patch
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 b616d024 --stdout > /tmp/b616d024.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/b616d024.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/b616d024.patch
|
|
```
|
|
|
|
**Step 2:** Apply
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/b616d024.patch
|
|
```
|
|
|
|
**Step 3:** Cargo.toml conflicts are likely — the sub-crate Cargo.tomls have different dependency lists on the branch. For each `.rej` file in a Cargo.toml:
|
|
- Main added `default-features = ["cuda"]` — manually add this to the branch's version
|
|
- Main may have version bumps — adopt them
|
|
|
|
**Step 4:** Also add `default-features = ["cuda"]` to any NEW sub-crate Cargo.tomls the branch created (ml-data, ml-benchmark, ml-deployment) that main didn't know about.
|
|
|
|
**Step 5:** Verify + commit
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
git add -A
|
|
git commit -m "forward-port(b616d024): IQN GPU PER weights, CUDA default features (path-adapted)"
|
|
```
|
|
|
|
### Task 3c: Eliminate CPU tensor ops (`801781a4`)
|
|
|
|
**Main's changes:** ml-core/gradient_accumulation.rs, ml-dqn/dqn.rs, ml-dqn/gpu_replay_buffer.rs (clean) + `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer)
|
|
|
|
**Step 1-5:** Same pattern as 3a — format-patch, sed trainer path, apply, fix, commit.
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 801781a4 --stdout > /tmp/801781a4.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/801781a4.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/801781a4.patch
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/801781a4.patch
|
|
# Fix .rej files, cargo check, commit
|
|
```
|
|
|
|
### Task 3d: Replace remaining CPU tensor allocations (`5191fa02`)
|
|
|
|
**Main's changes:** ml-dqn/distributional.rs, ml-dqn/dqn.rs, ml-dqn/quantile_regression.rs, ml-ppo/ppo.rs — ALL sub-crate files, no path rewrite needed.
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 5191fa02 --stdout > /tmp/5191fa02.patch
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/5191fa02.patch
|
|
# Should apply cleanly. Verify + commit.
|
|
```
|
|
|
|
### Task 3e: GPU searchsorted kernel (`0f45537e`)
|
|
|
|
**Main's changes:** ml-core/mixed_precision.rs, ml-dqn/gpu_replay_buffer.rs, ml-dqn/searchsorted_kernel.cu — all sub-crate.
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 0f45537e --stdout > /tmp/0f45537e.patch
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/0f45537e.patch
|
|
```
|
|
|
|
**Note:** `searchsorted_kernel.cu` is a new file — verify it's created in `crates/ml-dqn/src/`.
|
|
|
|
### Task 3f: BF16 mixed precision default (`7f3066e6`)
|
|
|
|
**Main's changes:** ml-core/mixed_precision.rs, ml-dqn/curiosity.rs, ml-dqn/network.rs, ml-hyperopt/traits.rs (all clean) + `ml/src/hyperopt/adapters/dqn.rs` (→ ml-hyperopt/adapters)
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 7f3066e6 --stdout > /tmp/7f3066e6.patch
|
|
sed -i 's|a/crates/ml/src/hyperopt/adapters/|a/crates/ml-hyperopt/src/adapters/|g' /tmp/7f3066e6.patch
|
|
sed -i 's|b/crates/ml/src/hyperopt/adapters/|b/crates/ml-hyperopt/src/adapters/|g' /tmp/7f3066e6.patch
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/7f3066e6.patch
|
|
```
|
|
|
|
### Task 3g: BF16 softmax overflow (`fb18e0f1`)
|
|
|
|
**Main's changes:** ml-dqn/distributional_dueling.rs, ml-dqn/rainbow_network.rs (clean) + `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer)
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 fb18e0f1 --stdout > /tmp/fb18e0f1.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/fb18e0f1.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/fb18e0f1.patch
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/fb18e0f1.patch
|
|
```
|
|
|
|
### Task 3-checkpoint: Verify Phase 3
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
SQLX_OFFLINE=true cargo clippy --workspace -- -D warnings 2>&1 | head -30
|
|
```
|
|
|
|
Commit any remaining fixups.
|
|
|
|
---
|
|
|
|
## Phase 4: The Monster Commit — GPU-Native Regime Classification (`c0c44a5f`)
|
|
|
|
This single commit touches **42 files** (+821/-514 lines) spanning cuda_pipeline, features, data_loaders, ensemble, hyperopt, trainers, and tests. It must be decomposed into per-destination patches.
|
|
|
|
### Task 4a: Extract and split the patch
|
|
|
|
**Step 1:** Generate the full patch
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 c0c44a5f --stdout > /tmp/c0c44a5f-full.patch
|
|
```
|
|
|
|
**Step 2:** Create per-destination copies with path rewrites
|
|
|
|
```bash
|
|
# Copy A: cuda_pipeline changes → ml-core
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-cuda.patch
|
|
sed -i 's|a/crates/ml/src/cuda_pipeline/|a/crates/ml-core/src/cuda_pipeline/|g' /tmp/c0c44a5f-cuda.patch
|
|
sed -i 's|b/crates/ml/src/cuda_pipeline/|b/crates/ml-core/src/cuda_pipeline/|g' /tmp/c0c44a5f-cuda.patch
|
|
|
|
# Copy B: features changes → ml-features
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-features.patch
|
|
sed -i 's|a/crates/ml/src/features/|a/crates/ml-features/src/|g' /tmp/c0c44a5f-features.patch
|
|
sed -i 's|b/crates/ml/src/features/|b/crates/ml-features/src/|g' /tmp/c0c44a5f-features.patch
|
|
|
|
# Copy C: trainers/dqn changes → ml-dqn/trainer
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-trainer.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/c0c44a5f-trainer.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/c0c44a5f-trainer.patch
|
|
|
|
# Copy D: hyperopt/adapters changes → ml-hyperopt/adapters
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-hyperopt.patch
|
|
sed -i 's|a/crates/ml/src/hyperopt/adapters/|a/crates/ml-hyperopt/src/adapters/|g' /tmp/c0c44a5f-hyperopt.patch
|
|
sed -i 's|b/crates/ml/src/hyperopt/adapters/|b/crates/ml-hyperopt/src/adapters/|g' /tmp/c0c44a5f-hyperopt.patch
|
|
|
|
# Copy E: ensemble changes → ml-ensemble
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-ensemble.patch
|
|
sed -i 's|a/crates/ml/src/ensemble/|a/crates/ml-ensemble/src/|g' /tmp/c0c44a5f-ensemble.patch
|
|
sed -i 's|b/crates/ml/src/ensemble/|b/crates/ml-ensemble/src/|g' /tmp/c0c44a5f-ensemble.patch
|
|
|
|
# Copy F: trainers/ppo changes → ml-ppo/trainer
|
|
cp /tmp/c0c44a5f-full.patch /tmp/c0c44a5f-ppo.patch
|
|
sed -i 's|a/crates/ml/src/trainers/ppo.rs|a/crates/ml-ppo/src/trainer.rs|g' /tmp/c0c44a5f-ppo.patch
|
|
sed -i 's|b/crates/ml/src/trainers/ppo.rs|b/crates/ml-ppo/src/trainer.rs|g' /tmp/c0c44a5f-ppo.patch
|
|
```
|
|
|
|
### Task 4b: Apply each sub-patch
|
|
|
|
**Step 1:** Apply in dependency order. Use `--reject` throughout.
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
|
|
# A: ml-core cuda_pipeline
|
|
git apply --reject /tmp/c0c44a5f-cuda.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# B: ml-features
|
|
git apply --reject /tmp/c0c44a5f-features.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# C: ml-dqn trainer
|
|
git apply --reject /tmp/c0c44a5f-trainer.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# D: ml-hyperopt adapters
|
|
git apply --reject /tmp/c0c44a5f-hyperopt.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# E: ml-ensemble
|
|
git apply --reject /tmp/c0c44a5f-ensemble.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# F: ml-ppo
|
|
git apply --reject /tmp/c0c44a5f-ppo.patch 2>&1 | grep -E "Applied|Rejected"
|
|
|
|
# G: The original patch for files that DIDN'T move (data_loaders, tests, examples, etc.)
|
|
git apply --reject /tmp/c0c44a5f-full.patch 2>&1 | grep -E "Applied|Rejected"
|
|
```
|
|
|
|
**Step 2:** Each patch will partially apply and partially reject (since each copy has ALL hunks but only some paths match). Resolve `.rej` files one by one.
|
|
|
|
**Step 3:** Handle special cases:
|
|
- `features/mod.rs` on main → merged into `ml-features/src/lib.rs` on branch. Manually read the diff hunk and apply to lib.rs.
|
|
- `trainers/dqn/smoke_tests/*` — main CREATED these files; branch DELETED the directory. **Decision: Skip.** These smoke tests tested the monolithic trainer; they need to be rewritten for ml-dqn's trainer structure. Create a TODO in the commit message.
|
|
- `trainers/tft_parquet.rs` — DELETED on branch. Skip (parquet removal intentional).
|
|
- `data_loaders/parquet_utils.rs` — DELETED on branch. Skip.
|
|
- `feature_cache.rs` — DELETED on branch. Skip.
|
|
- `hyperopt/shared_data.rs` → `ml-hyperopt/src/shared_data.rs` — apply shared_data changes with path rewrite.
|
|
|
|
**Step 4:** Clean up reject files
|
|
|
|
```bash
|
|
find . -name "*.rej" -type f
|
|
# Review each, apply manually or confirm skip, then delete
|
|
find . -name "*.rej" -type f -delete
|
|
```
|
|
|
|
### Task 4c: Compiler-driven fixup for regime classification
|
|
|
|
This is the most intensive fixup step. The regime classification commit changed function signatures and data flow across crate boundaries.
|
|
|
|
**Step 1:** Run compiler
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace 2>&1 | head -100
|
|
```
|
|
|
|
**Step 2:** Fix import paths. Common patterns:
|
|
```
|
|
# In ml-core/cuda_pipeline files:
|
|
use crate::mixed_precision::training_dtype → already correct (in ml-core)
|
|
|
|
# In ml-dqn/trainer files:
|
|
use crate::cuda_pipeline:: → use ml_core::cuda_pipeline::
|
|
use crate::features:: → use ml_features::
|
|
|
|
# In ml-hyperopt/adapters files:
|
|
use crate::trainers::dqn:: → use ml_dqn::trainer::
|
|
use crate::features:: → use ml_features::
|
|
|
|
# In ml-ensemble files:
|
|
use crate::features:: → use ml_features::
|
|
```
|
|
|
|
**Step 3:** Add missing crate dependencies to Cargo.toml files if needed (e.g., if ml-hyperopt now needs ml-features).
|
|
|
|
**Step 4:** Iterate: `cargo check`, fix, `cargo check`, fix... until clean.
|
|
|
|
**Step 5:** Commit
|
|
|
|
```bash
|
|
git add -A
|
|
git commit -m "forward-port(c0c44a5f): GPU-native regime classification with 42-dim features (decomposed + path-adapted)
|
|
|
|
Skipped: smoke_tests/ (deleted on branch), parquet_utils.rs, feature_cache.rs, tft_parquet.rs
|
|
TODO: Recreate DQN trainer smoke tests in crates/ml-dqn/tests/"
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 5: Heavy Commits (4 commits)
|
|
|
|
### Task 5a: GPU PER monitoring (`d12273e1`, 17 files, +1148/-115)
|
|
|
|
**Main's changes span:** cuda_pipeline (→ ml-core), trainers/dqn (→ ml-dqn/trainer), hyperopt/adapters/dqn (→ ml-hyperopt), smoke_tests (→ DELETED), + ml-dqn sub-crate files, ml-core files.
|
|
|
|
**Step 1:** Full rewrite-and-apply
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 d12273e1 --stdout > /tmp/d12273e1.patch
|
|
|
|
# Apply all path rewrites
|
|
sed -i 's|a/crates/ml/src/cuda_pipeline/|a/crates/ml-core/src/cuda_pipeline/|g' /tmp/d12273e1.patch
|
|
sed -i 's|b/crates/ml/src/cuda_pipeline/|b/crates/ml-core/src/cuda_pipeline/|g' /tmp/d12273e1.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/d12273e1.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/d12273e1.patch
|
|
sed -i 's|a/crates/ml/src/hyperopt/adapters/|a/crates/ml-hyperopt/src/adapters/|g' /tmp/d12273e1.patch
|
|
sed -i 's|b/crates/ml/src/hyperopt/adapters/|b/crates/ml-hyperopt/src/adapters/|g' /tmp/d12273e1.patch
|
|
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/d12273e1.patch
|
|
```
|
|
|
|
**Step 2:** The `smoke_tests/` hunks will fail (directory doesn't exist on branch). This is expected — these 5 files (~900 LOC) were deleted on the branch. The `.rej` files for smoke_tests can be safely deleted.
|
|
|
|
**Step 3:** Fix imports, cargo check, commit.
|
|
|
|
```bash
|
|
find . -name "*.rej" -delete
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
git add -A
|
|
git commit -m "forward-port(d12273e1): GPU PER monitoring fix (path-adapted, smoke_tests skipped)"
|
|
```
|
|
|
|
### Task 5b: Branching DQN with GPU Rainbow parity (`89c3fb89`, 10 files, +3207/-125)
|
|
|
|
**Main's changes:** ml-core/fill_simulator.rs, ml-core/lib.rs, ml-dqn/branching.rs (NEW), ml-dqn/dqn.rs, ml-dqn/lib.rs (all sub-crate — clean) + `ml/src/hyperopt/adapters/dqn.rs` (→ ml-hyperopt), `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer), `ml/src/trainers/dqn/trainer.rs` (→ ml-dqn/trainer), infra/scripts/train.sh, docs/
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 89c3fb89 --stdout > /tmp/89c3fb89.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/89c3fb89.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/89c3fb89.patch
|
|
sed -i 's|a/crates/ml/src/hyperopt/adapters/|a/crates/ml-hyperopt/src/adapters/|g' /tmp/89c3fb89.patch
|
|
sed -i 's|b/crates/ml/src/hyperopt/adapters/|b/crates/ml-hyperopt/src/adapters/|g' /tmp/89c3fb89.patch
|
|
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/89c3fb89.patch
|
|
```
|
|
|
|
**Note:** `branching.rs` is a NEW file that goes into `ml-dqn/src/` — should apply cleanly. Verify `ml-dqn/src/lib.rs` includes `pub mod branching;`.
|
|
|
|
Fix imports, cargo check, commit.
|
|
|
|
### Task 5c: Eliminate OOM in hyperopt (`fe223b38`, 9 files, +477/-129)
|
|
|
|
**Main's changes:** ml-dqn/dqn.rs, ml-dqn/noisy_layers.rs, ml-hyperopt/traits.rs (clean) + `ml/src/cuda_pipeline/gpu_experience_collector.rs` (→ ml-core), `ml/src/hyperopt/adapters/dqn.rs` (→ ml-hyperopt), `ml/src/trainers/dqn/config.rs` (→ ml-dqn/trainer), `ml/src/trainers/dqn/trainer.rs` (→ ml-dqn/trainer), ml/tests/* (stay in ml)
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 fe223b38 --stdout > /tmp/fe223b38.patch
|
|
sed -i 's|a/crates/ml/src/cuda_pipeline/|a/crates/ml-core/src/cuda_pipeline/|g' /tmp/fe223b38.patch
|
|
sed -i 's|b/crates/ml/src/cuda_pipeline/|b/crates/ml-core/src/cuda_pipeline/|g' /tmp/fe223b38.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/fe223b38.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/fe223b38.patch
|
|
sed -i 's|a/crates/ml/src/hyperopt/adapters/|a/crates/ml-hyperopt/src/adapters/|g' /tmp/fe223b38.patch
|
|
sed -i 's|b/crates/ml/src/hyperopt/adapters/|b/crates/ml-hyperopt/src/adapters/|g' /tmp/fe223b38.patch
|
|
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/fe223b38.patch
|
|
```
|
|
|
|
Fix, check, commit.
|
|
|
|
### Task 5d: Retry branching action decomposition (`1b9f09fc`)
|
|
|
|
If this was skipped in Phase 2 because `branching.rs` didn't exist yet:
|
|
|
|
```bash
|
|
git cherry-pick 1b9f09fc
|
|
```
|
|
|
|
Should apply cleanly now that `89c3fb89` added `branching.rs`.
|
|
|
|
---
|
|
|
|
## Phase 6: CI/Metrics Mixed Commits (2 commits)
|
|
|
|
### Task 6a: Unblock CPU service builds (`7751f761`)
|
|
|
|
**Main's changes:** Cargo.toml (root), ml-dqn/regime_conditional.rs (clean), `ml/src/trainers/dqn/trainer.rs` (→ ml-dqn/trainer), infra/*
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 7751f761 --stdout > /tmp/7751f761.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/7751f761.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/7751f761.patch
|
|
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/7751f761.patch
|
|
```
|
|
|
|
### Task 6b: Wire training pod scraping (`e89fbc2b`)
|
|
|
|
**Main's changes:** `ml/src/trainers/dqn/trainer.rs` (→ ml-dqn/trainer), `ml/src/trainers/ppo.rs` (→ ml-ppo/trainer.rs), infra/*
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt
|
|
git format-patch -1 e89fbc2b --stdout > /tmp/e89fbc2b.patch
|
|
sed -i 's|a/crates/ml/src/trainers/dqn/|a/crates/ml-dqn/src/trainer/|g' /tmp/e89fbc2b.patch
|
|
sed -i 's|b/crates/ml/src/trainers/dqn/|b/crates/ml-dqn/src/trainer/|g' /tmp/e89fbc2b.patch
|
|
sed -i 's|a/crates/ml/src/trainers/ppo.rs|a/crates/ml-ppo/src/trainer.rs|g' /tmp/e89fbc2b.patch
|
|
sed -i 's|b/crates/ml/src/trainers/ppo.rs|b/crates/ml-ppo/src/trainer.rs|g' /tmp/e89fbc2b.patch
|
|
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git apply --reject /tmp/e89fbc2b.patch
|
|
```
|
|
|
|
Fix, check, commit.
|
|
|
|
---
|
|
|
|
## Phase 7: Visibility & Import Fixup Pass
|
|
|
|
After all patches are applied, some items may have `pub(crate)` visibility that's now insufficient across crate boundaries.
|
|
|
|
### Task 7a: Full compiler sweep
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
SQLX_OFFLINE=true cargo check --workspace 2>&1 | tee /tmp/forward-port-errors.log
|
|
grep "error\[" /tmp/forward-port-errors.log | sort -u | head -50
|
|
```
|
|
|
|
### Task 7b: Fix visibility errors
|
|
|
|
Common patterns:
|
|
- `pub(crate) fn foo()` in ml-core that ml-dqn now calls → change to `pub fn foo()`
|
|
- `pub(crate) struct Bar` in ml-core used by ml-hyperopt → change to `pub struct Bar`
|
|
|
|
### Task 7c: Fix missing dependency declarations
|
|
|
|
If ml-hyperopt now imports ml-features but it's not in Cargo.toml:
|
|
```toml
|
|
[dependencies]
|
|
ml-features = { workspace = true }
|
|
```
|
|
|
|
### Task 7d: Clippy clean
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo clippy --workspace -- -D warnings 2>&1 | head -50
|
|
```
|
|
|
|
Fix any new clippy warnings introduced by forward-ported code.
|
|
|
|
### Task 7e: Commit fixup
|
|
|
|
```bash
|
|
git add -A
|
|
git commit -m "fix: resolve visibility and import issues from forward-port"
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 8: Final Verification
|
|
|
|
### Task 8a: Full workspace build
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo check --workspace
|
|
```
|
|
|
|
Expected: success, 0 errors.
|
|
|
|
### Task 8b: Full clippy
|
|
|
|
```bash
|
|
SQLX_OFFLINE=true cargo clippy --workspace -- -D warnings
|
|
```
|
|
|
|
Expected: 0 errors, 0 warnings (excluding known ml-dqn dead field warnings from branch).
|
|
|
|
### Task 8c: Test count comparison
|
|
|
|
```bash
|
|
# Run all ml-* tests
|
|
for crate in crates/ml-*/; do
|
|
name=$(basename "$crate")
|
|
echo -n "$name: "
|
|
SQLX_OFFLINE=true cargo test -p "$name" --lib 2>&1 | grep "test result" | tail -1
|
|
done
|
|
|
|
# Run ml orchestration tests
|
|
echo -n "ml: "
|
|
SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | grep "test result" | tail -1
|
|
```
|
|
|
|
Compare totals with Phase 0 baseline. Total should be ≥ baseline (main added tests).
|
|
|
|
### Task 8d: Squash or keep history
|
|
|
|
**Option A (recommended):** Keep granular forward-port commits for traceability:
|
|
```
|
|
forward-port(e35ead5f): wire GPU PER into hot path (path-adapted)
|
|
forward-port(b616d024): IQN GPU PER weights, CUDA default features (path-adapted)
|
|
...
|
|
```
|
|
|
|
**Option B:** Squash all forward-port commits into one:
|
|
```bash
|
|
git rebase -i backup/ml-split-p2-before-forward-port
|
|
# Mark all forward-port commits as "squash"
|
|
```
|
|
|
|
### Task 8e: Update plan document
|
|
|
|
Add a completion note to `docs/plans/2026-03-08-ml-crate-split-phase2.md` noting that main's GPU changes have been forward-ported.
|
|
|
|
---
|
|
|
|
## Skip List (Merge Commits)
|
|
|
|
These are merge commits on main — skip them entirely, their content is included in the non-merge commits:
|
|
|
|
- `06d0a8d6` Merge branch 'feature/dqn-branching'
|
|
- `3a37454e` Merge branch 'feature/dqn-branching'
|
|
- `3c3812d9` Merge branch 'worktree-gpu-hotpath-audit'
|
|
|
|
---
|
|
|
|
## Deleted File Triage Summary
|
|
|
|
| File | Decision | Reason |
|
|
|------|----------|--------|
|
|
| `parquet_utils.rs` | Skip | Branch intentionally deleted all parquet code (-3K LOC) |
|
|
| `feature_cache.rs` | Skip | Superseded by ml-features architecture |
|
|
| `tft_parquet.rs` | Skip | Parquet removal |
|
|
| `smoke_tests/feature_coverage.rs` | TODO | 156 LOC — recreate in ml-dqn/tests/ |
|
|
| `smoke_tests/gpu_residency.rs` | TODO | 272 LOC — recreate in ml-dqn/tests/ |
|
|
| `smoke_tests/helpers.rs` | TODO | 85 LOC — recreate in ml-dqn/tests/ |
|
|
| `smoke_tests/training_stability.rs` | TODO | 254 LOC — recreate in ml-dqn/tests/ |
|
|
| `smoke_tests/performance.rs` | TODO | 146 LOC — recreate in ml-dqn/tests/ |
|
|
|
|
Smoke tests total ~900 LOC. They tested the monolithic DQN trainer. After the forward-port, create a follow-up task to rewrite them as integration tests in `crates/ml-dqn/tests/`.
|
|
|
|
---
|
|
|
|
## Rollback
|
|
|
|
If anything goes catastrophically wrong:
|
|
|
|
```bash
|
|
cd /home/jgrusewski/Work/foxhunt/.worktrees/ml-split-p2
|
|
git reset --hard backup/ml-split-p2-before-forward-port
|
|
```
|